Не удается прочитать файл - FileNotFoundException - Android 11, составить, ActivityResultContracts, READ_EXTERNAL_STORAGE

Я пытаюсь прочитать файл с внешнего хранилища /some/path/somefile.txt

В манифесте у меня есть <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Когда я нажимаю кнопку, чтобы попытаться прочитать файл, выбранный ActivityResultContracts.OpenDocument() я получаю

      java.io.FileNotFoundException: /document/primary:some/path/somefile.txt: open failed: ENOENT (No such file or directory)

Вот мой код:

      @OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ReadFileScreen() {
  val readPermissionState = rememberPermissionState(
    android.Manifest.permission.READ_EXTERNAL_STORAGE
  )
  val pickedFileUriState = remember { mutableStateOf<Uri?>(null) }
  val launcher =
    rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocument()) { result ->
      pickedFileUriState.value = result
    }
  Column {
    Button(onClick = readPermissionState::launchPermissionRequest) {
      Text("request read permission")
    }
    PermissionRequired(readPermissionState, {}, {}) {
      Button(onClick = { launcher.launch(arrayOf("*/*")) }
      ) {
        Text("pick file")
      }
      if (pickedFileUriState.value != null) Button(onClick = { readTextFile(pickedFileUriState.value!!) }
      ) {
        Text("read file")
      }
    }
  }
}

fun readTextFile(uri: Uri) {
  try {
    val text = File(uri.path).readText()
    println(text)
  } catch (e: Exception) {
    e.printStackTrace()
  }
}

1 ответ

Благодаря @ianhanniballake ссылка научила меня, как правильно получить доступ к файлу, выбранному пользователем.

Вот код, который я придумал:

      @OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ReadFileScreen() {
  val context = LocalContext.current
  val pickedFileUriState = remember { mutableStateOf<Uri?>(null) }
  val launcher =
    rememberLauncherForActivityResult(contract = ActivityResultContracts.OpenDocument()) { result ->
      pickedFileUriState.value = result
    }
  Column {
    Button(onClick = { launcher.launch(arrayOf("*/*")) }
    ) {
      Text("pick file")
    }
    if (pickedFileUriState.value != null)
      Button(onClick = {
        readTextFromUri(context, pickedFileUriState.value!!)
      }
      ) {
        Text("read file")
      }
  }
}

private fun readTextFromUri(context: Context, uri: Uri) {
  try {
    val stringBuilder = StringBuilder()
    context.contentResolver.openInputStream(uri)?.use { inputStream ->
      BufferedReader(InputStreamReader(inputStream)).use { reader ->
        var line: String? = reader.readLine()
        while (line != null) {
          stringBuilder.append(line)
          line = reader.readLine()
        }
      }
    }
    val text = stringBuilder.toString()
    Log.d("xxx", "text $text")
  } catch (e: IOException) {
    e.printStackTrace()
  }
}
Другие вопросы по тегам