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访问,步骤如下:
- 改造
getSongs()方法,查询媒体库时除了歌曲的标题、歌手、路径之外,额外获取音频对应的MediaStore.Audio.Media._ID字段,和歌曲信息一起存在你的Song实体类中。 - 启动播放器传参时,把歌曲的id也一起传递,或者在
Song类中增加获取对应Uri的方法:
// 单个音频的Uri构造方式 Uri audioUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 你查询到的歌曲id);
- 给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
相关产品推荐
相关产品推荐

