You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:45:03