如何处理应用生成的图片,重启应用后URI权限丢失无法访问怎么办?
问题根因
为什么丢失URI权限且调用takePersistableUriPermission报错
takePersistableUriPermission()仅适用于通过系统存储访问框架(SAF)的ACTION_OPEN_DOCUMENT/ACTION_CREATE_DOCUMENT等接口返回的URI,这类URI是系统授予的临时权限,才支持申请持久化授权。你通过FileProvider.getUriForFile()生成的URI,是设计用来给第三方应用临时授权访问你应用内文件的,本身不存在可持久化的权限授予规则,所以调用必然抛出SecurityException。- 你自己的应用对
getExternalFilesDir(应用专属外部存储目录)下的所有文件默认拥有永久读写权限,完全不需要通过URI+权限申请的方式访问,强行用FileProvider URI反而会引入临时权限失效的问题。
正确实现方案
你不需要改动文件拷贝的核心逻辑,只需要修改存储的标识和读取逻辑即可:
- 文件拷贝完成后,不要存储FileProvider生成的URI字符串,直接存储拷贝后文件的绝对路径字符串到数据库
- 后续读取文件生成Bitmap、或执行上传逻辑时,直接用存储的路径创建File对象读取即可,不需要通过ContentResolver访问URI
修改后的代码示例:
文件拷贝逻辑
val copyOfFile = createFile( application.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileMetaData.extension, fileMetaData.fileName, true ) val outPut = FileOutputStream(copyOfFile) inputStream.copyTo(outPut) // 直接存文件绝对路径,删除原有URI生成、持久化权限申请的逻辑 return CopyFileResult( copyOfFile.name, fileMetaData.extension, copyOfFile.absolutePath )
文件读取逻辑
val filePath = document.filePath!! // 读取数据库存储的绝对路径 val targetFile = File(filePath) // 直接读取文件生成Bitmap,也可以直接读取流传入上传框架 val bitmap = BitmapFactory.decodeFile(targetFile.absolutePath) // 如果你确实需要给其他第三方组件/应用提供文件访问入口,临时生成FileProvider URI即可: // val uri = FileProvider.getUriForFile(application, application.packageName, targetFile)
补充注意点
- 应用专属目录下的文件不会随应用重启丢失访问权限,只要用户不手动清除应用数据,你都可以正常访问
- 该方案适配所有Android版本,不需要申请全量存储权限,符合Google Play权限规范
- 如果用WorkManager实现后台上传,WorkManager可以直接访问应用专属目录下的文件,不需要额外权限配置
内容的提问来源于stack exchange,提问作者Andreas1234
相关产品推荐
相关产品推荐

