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

安卓10中MediaRecorder的setOutputFile如何适配分区存储Uri

安卓分区存储场景下 MediaRecorder 录音输出适配

核心适配思路

安卓10+上线分区存储机制后,不推荐通过非正规手段将公开可访问的Uri解析为真实文件路径——这类实现不仅兼容性差,在安卓11及以上版本会直接触发权限拦截。MediaRecorder本身原生支持通过FileDescriptor作为输出目标,完全可以跳过「获取物理文件路径」的环节,直接基于拿到的可写Uri完成录音输出。

原代码中需要删除的两行逻辑:

recordingName = getFilename();
recorder.setOutputFile(recordingName);

替换为基于Uri的FileDescriptor输出逻辑即可,其他录音配置(音频源、输出格式、编码器、监听回调)的代码完全不需要改动。

调整后的核心实现

public void startRecording() {
    recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setOutputFormat(output_formats[currentFormat]);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

    // 提前通过MediaStore API/用户授权拿到可写的录音输出Uri
    Uri outputUri = createAudioOutputUri();
    ParcelFileDescriptor pfd = null;
    try {
        // 通过Uri打开可写的文件描述符
        pfd = getContentResolver().openFileDescriptor(outputUri, "w");
        // 直接将文件描述符传给MediaRecorder,无需传入物理文件路径
        recorder.setOutputFile(pfd.getFileDescriptor());

        recorder.setOnErrorListener(errorListener);
        recorder.setOnInfoListener(infoListener);
        recorder.prepare();
        recorder.start();
        handler.post(updateVisualizer);
    } catch (IllegalStateException | IOException e) {
        e.printStackTrace();
    }
}

其中创建录音输出Uri的适配方法,不需要申请额外存储权限:

private Uri createAudioOutputUri() {
    ContentValues recordInfo = new ContentValues();
    String fileName = "录音_" + System.currentTimeMillis() + ".amr";
    recordInfo.put(MediaStore.Audio.Media.DISPLAY_NAME, fileName);
    recordInfo.put(MediaStore.Audio.Media.MIME_TYPE, "audio/amr");
    // 安卓Q及以上指定录音存储的公共相对路径
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        recordInfo.put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/应用录音目录/");
    }
    // 向媒体库插入条目拿到可直接写入的Uri
    return getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, recordInfo);
}

关键注意点

  • 全程不需要调用各类第三方工具类把Uri转成本地物理路径,这类方案在高版本安卓上的兼容性没有保障,完全违背分区存储的设计原则
  • 打开文件描述符时要传入正确的访问权限,新建空录音文件用"w"权限即可,需要追加写入的场景用"rw"权限
  • ParcelFileDescriptor的关闭时机要对齐录音流程:必须在录音停止、MediaRecorder.release()完成之后再释放,避免提前关闭导致录音内容写入失败、文件损坏

内容的提问来源于stack exchange,提问作者user3661581

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 03:15:04