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

使用MediaStore API保存音频时insert方法崩溃或返回null怎么解决?

问题原因与修复方案

1. 最初崩溃的原因

最开始仅传入DISPLAY_NAME就调用insert方法触发崩溃,是因为Android 10(API 29)及以上版本的MediaProvider处理公共媒体写入请求时,缺少必填参数导致底层解析文件属性时触发空指针,低版本系统虽然校验宽松,但也建议补全必要参数避免适配问题。

2. 新增代码后insert返回null的原因

你新增的代码存在三个核心问题:

  • 路径拼接错误:${directory}${song?.title}未添加路径分隔符,生成的路径格式非法,例如目录路径和文件名直接拼接为/storage/emulated/0/Android/data/包名/files/Music我的歌曲.mp3,非法路径会直接导致insert请求被系统拒绝
  • 字段使用错误:MediaStore.Audio.AudioColumns.DATA在Android 10及以上版本已被标记为只读,手动赋值会被系统忽略,部分定制ROM甚至会直接驳回写入请求
  • 权限缺失:未申请对应存储权限,Android 12及以下需要WRITE_EXTERNAL_STORAGE权限,Android 13及以上需要READ_MEDIA_AUDIO权限,权限不足会直接返回null

3. 完整修复方案

3.1 声明并申请存储权限

首先在AndroidManifest.xml中添加对应权限:

<!-- Android 12及以下适用 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 13及以上适用 -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

运行时先动态申请对应权限,拿到权限授权后再执行写入逻辑。

3.2 正确构造ContentValues参数

适配不同Android版本的写入规则,参考代码如下:

ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Media.DISPLAY_NAME, "My Song.mp3");
values.put(MediaStore.Audio.Media.TITLE, "My Song");
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg");

// Android 10及以上版本使用RELATIVE_PATH指定存储目录,不需要手动拼接路径
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    values.put(MediaStore.Audio.Media.RELATIVE_PATH, Environment.DIRECTORY_MUSIC);
    values.put(MediaStore.Audio.Media.IS_PENDING, 1); // 标记为待写入状态,避免写入过程中被其他应用扫描
} else {
    // 低版本手动拼接合法路径
    File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
    File audioFile = new File(musicDir, "My Song.mp3");
    values.put(MediaStore.Audio.Media.DATA, audioFile.getAbsolutePath());
}

ContentResolver resolver = getContentResolver();
Uri audioUri = resolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
if (audioUri != null) {
    // 拿到URI后打开输出流写入音频数据
    try (OutputStream os = resolver.openOutputStream(audioUri)) {
        // 此处写入你的音频二进制数据
        // ......
        // 写入完成后更新待写入状态(仅Android 10+需要)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            values.clear();
            values.put(MediaStore.Audio.Media.IS_PENDING, 0);
            resolver.update(audioUri, values, null, null);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.3 额外注意事项

如果你仅需要将音频保存在应用专属目录下,不需要被其他音频应用扫描到,不需要使用MediaStore,直接用File API读写即可,只有需要将文件共享到系统媒体库时才需要调用MediaStore接口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:24:06