Android Studio字符串赋值失效,Firebase双文件上传链接获取问题
问题:Firebase上传MP3与封面后,封面链接无法写入实时数据库
实现流程
- 选择本地MP3 Uri
- 将MP3上传至Firebase Storage
- 提取MP3元数据(名称、艺术家、专辑封面)
- 上传专辑封面至Firebase Storage
- 在Firebase实时数据库创建包含MP3下载链接、封面下载链接、名称、艺术家的Song对象
异常现象
在MP3上传成功的回调中提取元数据并上传封面,封面上传成功后将下载链接赋值给变量,但后续创建Song对象并写入数据库时,该变量始终为空。尝试过静态、非静态、局部变量等多种声明方式,问题依旧。
问题根源
Firebase的putBytes()(封面上传)和getDownloadUrl()都是异步执行的非阻塞操作。当前代码中,触发封面上传后立刻执行创建Song对象的逻辑,此时封面上传的异步任务还未完成,变量还没被赋值,导致写入数据库时封面链接为空。封面上传成功的回调会在主线程空闲时才执行,此时数据库写入操作早已完成。
修复代码
将创建Song对象并写入数据库的逻辑,移至封面上传成功的回调内部,同时优化getDownloadUrl()的处理(避免用while循环阻塞线程,改用回调链式调用):
private void uploadFile() { if (!filename.getText().toString().equals("") && imgView != null) { StorageReference mp3ref = mp3StorageRef.child(SongName.getText().toString().trim() + "_" + System.currentTimeMillis() + "." + getFileExtension(Mp3_uri)); mp3ref.putFile(Mp3_uri) .addOnSuccessListener(taskSnapshot -> { Handler handler = new Handler(); handler.postDelayed(() -> progressBar.setProgress(0), 500); MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); mediaMetadataRetriever.setDataSource(getContext(), Mp3_uri); String name = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); byte[] art = mediaMetadataRetriever.getEmbeddedPicture(); // 获取MP3的下载链接 taskSnapshot.getStorage().getDownloadUrl() .addOnSuccessListener(mp3DownloadUrl -> { // 上传封面 StorageReference cover = coverStorageRef.child("cover_" + name + "_" + System.currentTimeMillis() + ".jpg"); cover.putBytes(art) .addOnSuccessListener(coverTaskSnapshot -> { // 获取封面下载链接 coverTaskSnapshot.getStorage().getDownloadUrl() .addOnSuccessListener(coverDownloadUrl -> { // 两个链接都获取到后,创建Song对象并写入数据库 Song song = new Song(name, artist, coverDownloadUrl.toString(), mp3DownloadUrl.toString()); String uploadId = databaseReference.push().getKey(); databaseReference.child(uploadId).setValue(song); Toast.makeText(getContext(), "Upload Success", Toast.LENGTH_SHORT).show(); }); }) .addOnFailureListener(e -> Toast.makeText(getContext(), "Cover Upload Failed", Toast.LENGTH_SHORT).show()); }) .addOnFailureListener(e -> Toast.makeText(getContext(), "Failed to get MP3 URL", Toast.LENGTH_SHORT).show()); }) .addOnFailureListener(e -> Toast.makeText(getContext(), "MP3 Upload Failed", Toast.LENGTH_SHORT).show()) .addOnProgressListener(snapshot -> { double progress = (100.0 * snapshot.getBytesTransferred() / snapshot.getTotalByteCount()); progressBar.setProgress((int) progress); }); } else { Toast.makeText(getContext(), "No File Selected", Toast.LENGTH_SHORT).show(); } }
内容的提问来源于stack exchange,提问作者Kaiser
相关产品推荐
相关产品推荐

