适配Scoped Storage时MediaStore.getMediaUri()返回空游标是什么原因?
问题1:MediaStore.getDocumentUri()的使用逻辑
你的理解完全正确,这个API本身就是反向转换专用,仅能接收「已经通过MediaStore.getMediaUri()从原生MediaStore URI转换得到的SAF URI」作为入参,才能正确回传对应的原生MediaStore URI。
如果传入普通SAF URI,哪怕文件是你自己通过MediaStore API创建的,只要没有经过getMediaUri()的转换链路,权限匹配逻辑不通过,就会直接抛出不可恢复的SecurityException,这是系统预设的正常行为。
问题2:游标始终返回0是否正常
这是正常现象,触发这个问题的原因通常是你没有满足getMediaUri()的生效前提:
- 传入的SAF docUri对应的文件必须存放在MediaStore收录的公共媒体目录(DCIM、Pictures、Downloads、Movies、Music等)下,存放在应用专属目录、第三方应用沙盒目录、非公共目录的文件不会被MediaStore收录,自然查询不到结果
- 你没有针对拿到的SAF URI申请持久化权限:通过SAF选择器拿到URI后需要主动调用
contentResolver.takePersistableUriPermission(docUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)获取长期访问权限,否则仅能在当次会话临时访问,无法查询对应的MediaStore条目 - 应用没有申请对应版本的媒体权限:安卓13及以上需要申请
READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO对应权限,安卓11-12需要申请READ_EXTERNAL_STORAGE权限,否则无法查询其他应用创建的公共媒体文件条目
问题3:getMediaUri()的设计意义
这个API的设计场景不是「任意SAF URI转可查询MediaStore URI」,而是配合MediaStore.getDocumentUri()做双向转换:当你有原生MediaStore URI,需要跨应用分享、持久化存储URI的时候,可以先转成SAF Document URI;后续需要对该文件做批量媒体元数据更新、加入系统相册合集等只有原生MediaStore URI支持的操作时,再用getMediaUri()转回来。只有在这个双向转换的链路里,得到的MediaStore URI才是可正常查询使用的。
验证方案
你可以按以下步骤测试:
- 用MediaStore API在公共相册目录创建一张图片,拿到原生MediaStore URI
- 调用
MediaStore.getDocumentUri()把它转成SAF URI - 再用
MediaStore.getMediaUri()把这个SAF URI转回去,此时查询返回的游标就会有正常数据
内容的提问来源于stack exchange,提问作者Jenix
相关产品推荐
相关产品推荐

