Android 9及以上系统播放本地MP3失败报prepare failed错误问题求助
问题原因
- 分区存储适配问题:Android 10(API 29)及以上系统默认开启分区存储机制,
Environment.getExternalStorageDirectory()方法已被官方废弃,普通应用即使申请了读写外部存储权限,也无法直接通过原始文件路径访问公共目录下的文件。MediaPlayer 作为独立进程运行,无法直接获取你应用的文件访问权限,所以读取文件失败触发报错。部分定制ROM的Android 9系统也对公共目录文件访问做了额外限制,同样会触发该问题。 - 权限适配问题:如果你的应用 targetSdkVersion >= 33,原有
READ_EXTERNAL_STORAGE权限已失效,需要申请READ_MEDIA_AUDIO权限才能访问公共目录的音频文件。 - 文件写入规则问题:如果你生成MP3文件时是直接通过原始路径写入公共目录,没有通过MediaStore接口注册文件信息,系统的媒体库不会识别该文件,其他应用也无法获取到该文件的访问权限,就会出现其他应用也打不开的情况。
解决方案
临时适配方案(仅适用于API 29设备)
在AndroidManifest.xml的<application>节点添加属性,关闭分区存储的限制:
android:requestLegacyExternalStorage="true"
注意该属性在API 30及以上系统无效,仅可作为临时过渡方案使用。
长期适配方案(兼容所有Android版本)
- 优先使用应用私有目录存储音频
如果该音频文件仅需你的应用自身访问,不要存在公共目录,改为存储到应用私有外部存储目录,获取路径的代码如下:
// 该路径下的文件你的应用可直接访问,无需申请外部存储权限 String privateAudioDir = getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath(); String filePath = privateAudioDir + "/20210907144451.mp3";
- 公共目录文件通过Uri访问
如果需要存放在公共目录让其他应用也能访问,写入和读取都要通过MediaStore接口操作:
- 写入文件时通过ContentResolver向MediaStore插入音频记录,拿到Uri后写入文件流,完成后系统媒体库会自动识别该文件。
- 读取文件时不要直接传原始路径,先通过MediaStore查询到对应音频的Uri,再将Uri传给MediaPlayer:
// 示例:通过Uri设置数据源 player.setDataSource(context, audioUri);
- 高版本权限适配
targetSdkVersion >=33时,在Manifest中替换原有存储权限为音频专属权限,并在运行时动态申请:
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- 确认文件写入完成
生成MP3文件时确保输出流已完全关闭、文件写入结束后再调用播放逻辑,避免文件不完整导致的加载失败。
内容的提问来源于stack exchange,提问作者Mohamad Hasan Salmaaniyaan
相关产品推荐
相关产品推荐

