Android 11使用ResultLauncher复制文件及获取带读权限Uri的问题咨询
问题根因
- 你对系统返回的授权Uri做了
Uri.parse(it.toString().replace("%3A", ":"))篡改操作,Android系统授予的临时读取权限仅和原始返回的Uri绑定,修改后的Uri不持有任何访问权限,直接触发权限拒绝错误。 - 你当前使用的
FileProvider配置和当前问题无关,该配置仅用于你的应用向其他应用分享自身目录下的文件,读取系统返回的外部文件Uri不需要该配置。
修复方案
方案1:直接修复现有逻辑
删除对Uri的修改操作,直接使用registerForActivityResult返回的原始Uri即可,修改后代码如下:
singleTypeResultLauncher = fragment.registerForActivityResult(ActivityResultContracts.GetContent()){ result -> result?.let{ originalUri -> // 移除Uri替换逻辑,直接使用原始返回的Uri val path = createCopyAndReturnRealPath(fragment.requireContext(), originalUri) } }
启动逻辑保持不变即可,createCopyAndReturnRealPath方法本身逻辑无问题,传入正确的授权Uri后不会出现权限报错。
方案2:高版本系统更稳定适配(推荐Android 11+使用)
将ActivityResultContracts.GetContent替换为专门用于访问公共文档的ActivityResultContracts.OpenDocument,可以获得更稳定的权限,还支持持久化权限让应用重启后仍可访问选中的文件,代码如下:
singleTypeResultLauncher = fragment.registerForActivityResult(ActivityResultContracts.OpenDocument()){ result -> result?.let{ originalUri -> // 可选:持久化Uri读取权限,应用重启后仍可访问该文件 fragment.requireContext().contentResolver.takePersistableUriPermission( originalUri, Intent.FLAG_GRANT_READ_URI_PERMISSION ) val path = createCopyAndReturnRealPath(fragment.requireContext(), originalUri) } } // 启动方式调整为传入MIME类型数组 singleTypeResultLauncher.launch(arrayOf("application/pdf"))
内容的提问来源于stack exchange,提问作者Asad
相关产品推荐
相关产品推荐

