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

Android MediaPlayer无法设置DataSource URI问题求助

解决SharedPreferences存储歌曲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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:50:21