Android 11 之后,我们无法直接使用 File I/O访问Android/data目录。通过使用SAF,我现在可以使用 DocumentFile 来遍历我想要的文件,但是当我想用另一个应用程序打开文件时,我发现我做不到。即使我传入了正确的 Uri 参数,其他应用程序也无法访问该文件,因为它没有权限,我可以理解。但是我找到了一个叫“MT Manager”的应用,我惊讶的发现它可以打开数据目录下任意文件夹中的文件,并可以使用其他第三方应用,这太神奇了,我完全看不懂。请帮忙,你知道该怎么做吗?
fun Context.openFile(uri: Uri) {
try {
val intent = Intent(Intent.ACTION_VIEW)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setDataAndType(uri, MapTable.getMIMEType(uri.toString()))
this.startActivity(intent)
Intent.createChooser(intent, "choose app")
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, "sorry cannot open it!", Toast.LENGTH_SHORT).show()
}
}
此代码对普通目录下的文件有效,但在Android 11之后的Android/data目录下无效。
这就是我找到的MT 经理
我能想到一个不太聪明的方法,就是将sdcard/Android/data目录下的文件复制到sdcard目录下,然后调用上面的方法。这有效,但还不够好。我不知道那是什么。如何实现呢,他的效果看起来很不错。
val extract = {
ctx.toast("please wait...")
val target = File(ROOT_DIR + fileModel.name)
GlobalThreadPools.getInstance().execute {
fileModel.documentFile?.let { doc ->
val fis = ctx.contentResolver.openInputStream(doc.uri)
fis?.let { `is` ->
val bis = BufferedInputStream(`is`)
val fos = FileOutputStream(target)
try {
val buffer = ByteArray(1024)
var len: Int
while (((bis.read(buffer)).also { len = it }) != -1) {
fos.write(buffer, 0, len)
}
Thread.sleep(100)
postUI {
ctx.openFile(target.path)
}
} catch (e: Exception) {
postUI {
ctx.toast("faild!")
}
} finally {
fos.close()
bis.close()
`is`.close()
}
}
}
}
}