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

Android录音合并MP3触发java.io.FileNotFoundException问题求助

解决Android录音合并MP3时的FileNotFoundException问题

咱们一步步拆解问题,从权限、路径、逻辑顺序三个核心方向来排查修复:

1. 补全动态存储权限(Android 6.0+必做)

你只在清单文件中声明了WRITE_EXTERNAL_STORAGE权限,但Android 6.0(API 23)及以上版本,这类危险权限需要动态申请,否则系统会直接拒绝读写请求,导致文件无法创建或访问。

添加动态权限申请代码(建议在录音前执行):

private static final int REQUEST_STORAGE_PERM = 101;

// 检查并申请存储权限
private void checkStoragePermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_STORAGE_PERM);
    }
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_STORAGE_PERM) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 权限获取成功,执行录音/合并操作
        } else {
            Toast.makeText(this, "需要存储权限才能录制和保存音频", Toast.LENGTH_SHORT).show();
        }
    }
}

注意:Android 10及以上可在<application>标签添加android:requestLegacyExternalStorage="true",暂时兼容旧存储逻辑,避免分区存储限制影响。

2. 修复目录创建与路径拼接问题

(1)用mkdirs()替代mkdir()

你当前用f.mkdir()创建目录,如果父目录(比如R.string.PATH对应的目录)不存在,mkdir()会创建失败。换成mkdirs()可以递归创建所有缺失的父目录:

File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
        + File.separator + Global.gContext.getResources().getString(R.string.PATH)
        + File.separator + "Luyin");
if(!f.exists()){
    f.mkdirs(); // 递归创建所有父目录
}

(2)规范路径拼接方式

voiceName的初始化建议用File的getAbsolutePath()方法,避免直接拼接File对象导致的格式异常:

String voiceName = f.getAbsolutePath() + File.separator;

(3)提前创建临时文件目录

录音临时文件的temp目录需要提前创建,否则MP3Recorder无法在不存在的目录下创建文件:

// 创建temp目录
File tempDir = new File(voiceName + "temp");
if (!tempDir.exists()) {
    tempDir.mkdirs();
}
// 生成临时录音文件
File tempAudioFile = new File(tempDir, sound + soundNum + ".mp3");
mRecorder = new MP3Recorder(tempAudioFile);

3. 调整合并逻辑的顺序与文件检查

(1)修正stop()方法的执行顺序

你当前先合并再检查文件是否存在,逻辑颠倒。应该先检查是否有可合并的录音片段,再执行合并,最后验证结果:

private void stop() {
    mRecorder.stop();
    // 先检查是否有录制的片段
    if (soundList.isEmpty()) {
        Global.show("请先录制声音");
        return;
    }
    alertDialog.setMessage("正在合成,请稍后……");
    alertDialog.show();
    // 执行合并
    heBingMp3();
    // 检查合并后的文件
    File mergedFile = new File(voiceName + sound + ".mp3");
    if (mergedFile.exists()) {
        wancheng = true;
        new DecodeAudioTask(mergedFile.getAbsolutePath()).execute();
    } else {
        Global.show("音频合成失败");
        alertDialog.dismiss();
    }
}

(2)完善heBingMp3()的异常防护

在合并时增加临时文件存在性检查,避免读取不存在的文件触发异常:

public void heBingMp3(){
    File mergedFile = new File(voiceName + sound + ".mp3");
    // 确保目标文件父目录存在
    if (!mergedFile.getParentFile().exists()) {
        mergedFile.getParentFile().mkdirs();
    }
    try (FileOutputStream out = new FileOutputStream(mergedFile, true)) {
        for(String tempPath : soundList){
            File tempFile = new File(tempPath);
            // 跳过不存在的临时文件
            if (!tempFile.exists()) continue;
            try (FileInputStream in = new FileInputStream(tempFile)) {
                byte[] bs = new byte[1024*4];
                int len;
                while((len=in.read(bs))!=-1){
                    out.write(bs,0,len);
                }
                tempFile.delete();
            }
        }
    }catch (Exception e){
        e.printStackTrace();
        Global.show("合并音频时出错");
    }
}

(3)规范soundList的添加逻辑

添加临时文件路径时,直接用tempAudioFile.getAbsolutePath(),避免手动拼接导致的路径错误:

// 录音完成后添加到列表
soundList.add(tempAudioFile.getAbsolutePath());

按照上面的步骤逐一调整,应该就能解决文件找不到的问题了。

内容的提问来源于stack exchange,提问作者Jcy.D.Shanks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:12:34