Android MediaPlayer无法设置DataSource URI问题求助
这个权限报错我太熟悉了!你遇到的是Android里临时URI权限失效的典型坑——你存在SharedPreferences里的只是URI的字符串文本,但系统给你的文件访问权限是「一次性临时权限」,一旦APP重启、后台被回收或者权限有效期过了,再用这个字符串重建的URI去访问文件,就会被系统拦下来,抛出SecurityException。
给你两个靠谱的解决方案,按需选择:
方案一:获取持久化URI权限
如果你是通过系统文件选择器(比如ACTION_OPEN_DOCUMENT)让用户选的歌曲,那可以把临时权限转成持久权限:
- 在你拿到用户选择的URI之后,立刻调用这行代码锁定权限:
getContentResolver().takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION ); - 之后再把URI的字符串形式存到SharedPreferences里。下次APP重启后,直接用这个字符串重建URI,就能正常访问了。
- 注意:这个操作必须在获取URI的同一个Activity里完成,而且只适用于通过系统文档选择器获取的URI,自己构造的普通文件URI不适用。
方案二:存储MediaStore歌曲ID而非完整URI
如果你的歌曲是从系统媒体库(MediaStore)里获取的,更推荐存歌曲的_ID字段:
- 从查询MediaStore的Cursor里拿到
MediaStore.Audio.Media._ID的值(是个Long类型),把这个ID存到SharedPreferences里。 - 需要播放时,用ID重建合法的URI:
long savedSongId = sharedPreferences.getLong("last_played_song_id", -1); if (savedSongId != -1) { Uri songUri = ContentUris.withAppendedId( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, savedSongId ); // 用这个songUri去播放就没问题了 } - 这个方法兼容性更强,尤其是Android 10+的Scoped Storage环境下,MediaStore的ID是持久有效的,只要歌曲没被用户删除,就能一直访问,还不用额外处理权限。
额外提醒
- 如果你之前已经存了无效的URI字符串,记得先清理掉SharedPreferences里的旧数据,换成上面两种方式之一。
- 别直接存文件路径!Android 10+已经限制了直接访问文件路径,很容易触发权限问题。
内容的提问来源于stack exchange,提问作者Hans-Martin Hannibal Lauridsen
相关产品推荐
相关产品推荐

