You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; 
    } 
}

问题分析与修复方案

核心问题

  1. Uri传递错误:UploadSong中onAudioFileSelected保存的是selectedAudioUri.getPath(),但ACTION_OPEN_DOCUMENT返回的是Content Uri,getPath()并非真实文件路径,而是类似/document/raw:/storage/emulated/0/Music/song.mp3的格式,导致后续UploadService无法定位到真实文件。
  2. 错误构建目标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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:24:58