You need to enable JavaScript to run this app. targetSdkVersion29已申请存储权限仍报EACCES错误无法播放外置存储音乐
优惠活动
大模型
产品
解决方案
定价
更多

targetSdkVersion29已申请存储权限仍报EACCES错误无法播放外置存储音乐

问题原因

你遇到的权限报错是Android 10(API级别29)引入的分区存储机制导致的:

  • targetSdkVersion设为29时,应用默认开启分区存储限制,即便你已经申请了READ_EXTERNAL_STORAGE权限,也无法直接通过原始文件路径访问外置SD卡上的公共媒体文件,只有内置存储的公共媒体目录可以通过路径访问。
  • 你本地raw目录的资源可以正常播放,是因为raw属于应用内部私有资源,不受外部存储权限限制。

解决方案

方案1:快速兼容(仅适用于targetSdk=29场景)

如果你暂时不想改造现有逻辑,只需要在AndroidManifest.xml的<application>节点添加如下属性,即可关闭分区存储限制,恢复原有文件路径访问能力:

<application
    ...
    android:requestLegacyExternalStorage="true">
    ...
</application>

注意:该属性仅在Android 10(API29)设备上生效,如果你后续升级targetSdk到30及以上,该配置会失效,必须使用下面的合规方案。


方案2:长期合规方案(兼容所有Android版本)

不要直接用文件路径访问媒体资源,改为通过系统MediaStore提供的Uri访问,步骤如下:

  1. 改造getSongs()方法,查询媒体库时除了歌曲的标题、歌手、路径之外,额外获取音频对应的MediaStore.Audio.Media._ID字段,和歌曲信息一起存在你的Song实体类中。
  2. 启动播放器传参时,把歌曲的id也一起传递,或者在Song类中增加获取对应Uri的方法:
// 单个音频的Uri构造方式
Uri audioUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 你查询到的歌曲id);
  1. 给MediaPlayer设置数据源时,直接传入构造好的Uri,不要用file://+路径的方式:
try {
    musicPlayer.setDataSource(this, audioUri);
    musicPlayer.prepare();
} catch (IOException e) {
    e.printStackTrace();
}

该方案不需要额外申请权限,原有READ_EXTERNAL_STORAGE权限即可满足要求,同时兼容Android 10及以上所有版本,也能正常读取外置SD卡的媒体文件。


内容的提问来源于stack exchange,提问作者Amine Ch 99

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 04:45:11