Android应用上传音频至Firebase丢失文件内容问题求助
Android Firebase音频上传文件为空(仅8.7KB)问题
本地5.06MB的音频文件上传到Firebase Storage后仅显示8.7KB,无实际音频内容,Logcat输出"Upload successful",模拟器与真机测试结果一致。
相关代码
UploadSong(输入控制类)
public class UploadSong extends AppCompatActivity { private FirebaseUser user; private ActivityResultLauncher<String> audioPickerLauncher; private String filePath; private TextView TVfilePathShow; private EditText ETSongAuthor; private EditText ETSongTitle; private FirebaseFirestore songDB; private CollectionReference songRef; @Override protected void onCreate(Bundle savedInstanceState) { user= FirebaseAuth.getInstance().getCurrentUser(); if (user != null && getIntent().getIntExtra("upload",1)==1){ super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_upload_song); audioPickerLauncher = registerForActivityResult(new AudioPickerContract(), this::onAudioFileSelected); TVfilePathShow = findViewById(R.id.songURL); ETSongAuthor = findViewById(R.id.songAuthor); ETSongTitle = findViewById(R.id.songTitle); songDB=FirebaseFirestore.getInstance(); songRef = songDB.collection("Songs"); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); } else if(user != null){ finish(); Intent openList = new Intent(this, MainPageAfterLoggedIn.class); startActivity(openList); } else { finish(); Intent openLogin = new Intent(this, MainActivity.class); startActivity(openLogin); } } public void selectFile(View view) { audioPickerLauncher.launch("audio/*"); } @SuppressLint("ResourceAsColor") private void onAudioFileSelected(Uri selectedAudioUri){ filePath = selectedAudioUri.getPath(); TVfilePathShow.setText(filePath); TVfilePathShow.setTextColor(R.color.black); } @SuppressLint("ResourceAsColor") public void upload(View view) { if (filePath == null){ TVfilePathShow.setText("Adj meg egy fajlt!"); TVfilePathShow.setTextColor(R.color.red); } else { Intent intent = new Intent(this, UploadService.class); intent.putExtra("fileUri", filePath); String songAuthor = ETSongAuthor.getText().toString(); String songTitle = ETSongTitle.getText().toString(); String[] filePathParts = filePath.split("/"); songRef.add(new song(songTitle,songAuthor,filePathParts[filePathParts.length-1]+"audio", user.getEmail())) .addOnSuccessListener(documentReference -> { Log.i(UploadSong.class.getName(),"Letrehozva"); }) .addOnFailureListener(documentReference -> { Log.e(UploadSong.class.getName(),"Error"); }); startService(intent); finish(); Intent intent2 = new Intent(this, MainPageAfterLoggedIn.class); startActivity(intent2); } } }
AudioPickerContract
public class AudioPickerContract extends ActivityResultContract<String, Uri> { @NonNull @Override public Intent createIntent(@NonNull Context context, String s) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType(s); return intent; } @Override public Uri parseResult(int i, @Nullable Intent intent) { if (intent == null || i != RESULT_OK) { return null; } return intent.getData(); } }
UploadService
public class UploadService extends Service { private static final String TAG = "UploadService"; private StorageReference storageRef; private static final String CHANNEL_ID = "UploadServiceChannel"; @Override public void onCreate(){ super.onCreate(); storageRef = FirebaseStorage.getInstance().getReference(); } @SuppressLint("ForegroundServiceType") @Override public int onStartCommand(Intent intent, int flags, int startId) { String fileUri = intent.getStringExtra("fileUri"); if (fileUri != null) { String[] fileUriParts = fileUri.split(":"); Uri contentUri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI; ContentResolver cR = getApplicationContext().getContentResolver(); Uri realFileUri = Uri.withAppendedPath(contentUri,fileUriParts[1]); startForeground(1,createNotification()); File file = new File(String.valueOf(realFileUri)); Log.i(TAG,String.valueOf(file.length())); Log.i(TAG,realFileUri.toString()); uploadFile(realFileUri); } return START_NOT_STICKY; } private void uploadFile(Uri fileUri) { StorageReference songsRef = storageRef.child("songs"); String[] fileUriParts = fileUri.toString().split("/"); StorageReference fileRef = songsRef.child(fileUriParts[fileUriParts.length-1]+".mp3"); Log.i(TAG,fileRef.toString()); ContentResolver cR = getApplicationContext().getContentResolver(); StorageMetadata metadata = new StorageMetadata.Builder() .setContentType("audio/mpeg") .build(); UploadTask uploadTask = fileRef.putFile(fileUri, metadata); uploadTask.addOnProgressListener(taskSnapshot -> { long bytesTransferred = taskSnapshot.getBytesTransferred(); long totalBytes = taskSnapshot.getTotalByteCount(); int progress = (int) ((100.0 * bytesTransferred) / totalBytes); Log.i(TAG,""+progress); updateProgressNotification(progress); }).addOnSuccessListener(taskSnapshot -> { Log.d(TAG, "Upload successful"); stopForeground(true); stopSelf(); }).addOnFailureListener(exception -> { Log.e(TAG, "Upload failed: " + exception.getMessage()); stopForeground(true); stopSelf(); }); } private Notification createNotification() { createNotificationChannel(); return new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Uploading...") .setContentText("Upload in progress") .setSmallIcon(R.drawable.baseline_arrow_upward_24) .build(); } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "Upload Channel"; String description = "Channel for upload progress notification"; NotificationManager notificationManager = getSystemService(NotificationManager.class); int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); channel.setDescription(description); notificationManager.createNotificationChannel(channel); } } private void updateProgressNotification(int progress) { Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Uploading...") .setContentText(progress + "% completed") .setProgress(100, progress, false) .setSmallIcon(R.drawable.baseline_arrow_upward_24) .build(); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.notify(1, notification); } private void cancelProgressNotification() { NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.cancel(1); } @Override public IBinder onBind(Intent intent) { return null; } }
问题分析与修复方案
核心问题
- Uri传递错误:
UploadSong中onAudioFileSelected保存的是selectedAudioUri.getPath(),但ACTION_OPEN_DOCUMENT返回的是Content Uri,getPath()并非真实文件路径,而是类似/document/raw:/storage/emulated/0/Music/song.mp3的格式,导致后续UploadService无法定位到真实文件。 - 错误构建目标Uri:
UploadService中拆分getPath()的结果并拼接INTERNAL_CONTENT_URI,得到的Uri不指向实际音频文件,最终上传的是空内容或无效小文件。
修复步骤
1. 传递完整Content Uri字符串
修改UploadSong的onAudioFileSelected方法,保存完整Uri字符串并优化显示:
@SuppressLint("ResourceAsColor") private void onAudioFileSelected(Uri selectedAudioUri){ filePath = selectedAudioUri.toString(); // 保存完整Uri字符串 TVfilePathShow.setText(selectedAudioUri.getLastPathSegment()); // 仅显示文件名,提升用户体验 TVfilePathShow.setTextColor(R.color.black); // 可选:获取持久访问权限,避免后续访问失败 final int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; getContentResolver().takePersistableUriPermission(selectedAudioUri, takeFlags); }
2. 修复UploadService的Uri解析逻辑
在UploadService的onStartCommand中,直接解析传递的Uri字符串,无需手动拼接:
@SuppressLint("ForegroundServiceType") @Override public int onStartCommand(Intent intent, int flags, int startId) { String fileUriStr = intent.getStringExtra("fileUri"); if (fileUriStr != null) { Uri fileUri = Uri.parse(fileUriStr); // 直接解析完整Content Uri startForeground(1, createNotification()); // 调试:验证文件大小 try { ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(fileUri, "r"); long fileSize = pfd.getStatSize(); Log.i(TAG, "实际文件大小: " + fileSize); pfd.close(); } catch (IOException e) { Log.e(TAG, "获取文件大小失败", e); } uploadFile(fileUri); } return START_NOT_STICKY; }
3. 修正Firestore文档中的文件名
在UploadSong的upload方法中,从真实Uri获取正确文件名(需将selectedAudioUri保存为成员变量):
// 先在UploadSong中添加成员变量:private Uri selectedAudioUri; // 修改onAudioFileSelected方法保存Uri:this.selectedAudioUri = selectedAudioUri; @SuppressLint("ResourceAsColor") public void upload(View view) { if (selectedAudioUri == null){ TVfilePathShow.setText("Adj meg egy fajlt!"); TVfilePathShow.setTextColor(R.color.red); } else { Intent intent = new Intent(this, UploadService.class); intent.putExtra("fileUri", selectedAudioUri.toString()); String songAuthor = ETSongAuthor.getText().toString(); String songTitle = ETSongTitle.getText().toString(); String fileName = selectedAudioUri.getLastPathSegment(); // 获取正确文件名 songRef.add(new song(songTitle,songAuthor, fileName, user.getEmail())) .addOnSuccessListener(documentReference -> { Log.i(UploadSong.class.getName(),"Letrehozva"); }) .addOnFailureListener(e -> { Log.e(UploadSong.class.getName(),"Error", e); }); startService(intent); finish(); Intent intent2 = new Intent(this, MainPageAfterLoggedIn.class); startActivity(intent2); } }
权限补充
确保在AndroidManifest.xml中添加对应权限:
<!-- Android 12及以下 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13及以上 --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- 前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
并在代码中动态申请权限。
内容的提问来源于stack exchange,提问作者user24494129
相关产品推荐
相关产品推荐

