Android11 Compose使用OpenDocument选文件读取时报FileNotFoundException如何解决
问题根因
- 你通过
ActivityResultContracts.OpenDocument()拿到的是系统存储访问框架(SAF)返回的Content URI,而非本地文件的真实路径,uri.path返回的是SAF的虚拟路径标识,直接用该路径创建File对象无法匹配到真实文件,因此抛出文件不存在异常。 - 通过SAF选取文件时,系统会自动授予你所选文件的临时读取权限,不需要提前申请
READ_EXTERNAL_STORAGE权限,权限申请相关逻辑可以直接删除。
修复方案
修改readTextFile方法,使用ContentResolver打开Content URI的输入流读取内容即可,示例代码如下:
fun readTextFile(context: Context, uri: Uri) { try { // 通过ContentResolver打开输入流读取内容 val text = context.contentResolver.openInputStream(uri)?.use { inputStream -> inputStream.bufferedReader().readText() } text?.let { println(it) } } catch (e: Exception) { e.printStackTrace() } }
Compose界面中调用时使用LocalContext.current获取Context即可,你也可以同步删除多余的权限申请逻辑,简化后的界面代码如下:
@Composable fun ReadFileScreen() { val pickedFileUriState = remember { mutableStateOf<Uri?>(null) } val context = LocalContext.current val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocument()) { result -> pickedFileUriState.value = result } Column { Button(onClick = { launcher.launch(arrayOf("*/*")) }) { Text("pick file") } pickedFileUriState.value?.let { uri -> Button(onClick = { readTextFile(context, uri) }) { Text("read file") } } } }
内容的提问来源于stack exchange,提问作者Tom Berghuis
相关产品推荐
相关产品推荐

