Android Kotlin 通过ACTION_OPEN_DOCUMENT获取外部存储文件触发FileProvider异常
错误原因
- 你混淆了
content://类型的Uri和本地文件路径的使用逻辑:ACTION_OPEN_DOCUMENT返回的是系统内容提供器返回的content://格式的Uri,不是本地文件的真实存储路径,你直接把这个Uri的字符串丢给File()构造函数,得到的是完全不存在的虚拟路径,自然没法被FileProvider匹配到你配置的根目录。 - 你的处理逻辑完全颠倒了FileProvider的作用:FileProvider是用来把你应用自己私有目录的本地文件,转换成
content://Uri分享给其他应用的,不是用来把其他应用/系统返回的content://Uri转成本地文件的。
解决方法
直接用系统返回的Uri读取文件即可,不需要经过FileProvider处理,你可以直接从这个Uri读取文件流,把zip包复制到你应用的私有目录下再执行恢复操作,示例代码如下:
try { // 直接获取返回的Uri,不要转成字符串再拼File val uri = data.data ?: run { // 处理Uri为空的异常 return@registerForActivityResult } // 直接通过ContentResolver打开输入流 contentResolver.openInputStream(uri)?.use { inputStream -> // 把zip包复制到你应用私有目录的目标路径,比如files目录下的backup.zip val targetFile = File(filesDir, "backup.zip") targetFile.outputStream().use { outputStream -> inputStream.copyTo(outputStream) } // 现在targetFile是你应用自己目录下的文件,可直接操作 if (targetFile.exists()) { restoreDatabase() } } ?: run { // 处理打开流失败的逻辑 } } catch (e: Exception) { Log.e("pickFile", e.toString()) }
如果你的restoreDatabase()方法需要传入文件路径,直接传入上面生成的targetFile.absolutePath即可,不需要再调用FileProvider做任何转换。
如果一定要直接访问外部存储的Download目录下的文件,也可以申请MANAGE_EXTERNAL_STORAGE权限(注意谷歌商店上架需要说明用途),直接通过路径读取文件,不需要用ACTION_OPEN_DOCUMENT选择。
内容的提问来源于stack exchange,提问作者Gabriel Ricci
相关产品推荐
相关产品推荐

