Из-за чего при выборе файла выбрасывается исключение FileNotFound?

Ссылка скопирована
1 ответ

Сейчас ситуация такая: изучаю Kotlin и, попутно, разработку под Android. Столкнулся со следующей проблемой.
Сейчас ситуация такая: простое приложение (стандартное Basic View Activity). При нажатии на кнопку пользователь выбирает файл, который приложение должно прочитать. Все хорошо до момента начала чтения файла, потом сразу выбрасывается исключение java.io.FileNotFoundException No such file or directory. Хотя название файла и путь к нему выводит в TextView, правда при проверке File.isFile говорит false. Как бы я не бился - результат не меняется. Я так понимаю, приложению необходимо толи какие-то разрешения указать, толи что-то еще. Ну и сам вопрос - что с этим можно сделать, ведь файл реально существует и пользователь его выбирает. Код могу добавить, но мне сто-то подсказывает, что причина не в коде, а в каких-то настройках. Заранее благодарю за ответ.

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Ирина WP Ответ

В Android после выбора файла через системный picker вы обычно получаете не обычный путь к файлу, а Uri вида content://.... Его нельзя корректно читать через File(path), поэтому File.isFile возвращает false, а затем вы ловите FileNotFoundException. Файл существует, но доступ к нему идёт через ContentResolver.

Правильная схема — читать поток:

val launcher = registerForActivityResult(
    ActivityResultContracts.OpenDocument()
) { uri: Uri? ->
    uri ?: return@registerForActivityResult
 
    contentResolver.openInputStream(uri)?.use { input ->
        val text = input.bufferedReader().readText()
        textView.text = text
    }
}

val launcher = registerForActivityResult( ActivityResultContracts.OpenDocument() ) { uri: Uri? -> uri ?: return@registerForActivityResult contentResolver.openInputStream(uri)?.use { input -> val text = input.bufferedReader().readText() textView.text = text } }

Запуск выбора:

launcher.launch(arrayOf("text/plain", "application/json", "*/*"))

launcher.launch(arrayOf("text/plain", "application/json", "*/*"))

Если доступ нужен не только прямо сейчас, а после перезапуска приложения, нужно сохранить persistable permission:

contentResolver.takePersistableUriPermission(
    uri,
    Intent.FLAG_GRANT_READ_URI_PERMISSION
)

contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION )

Но это работает, если вы используете OpenDocument, а не просто GetContent. Для временного чтения достаточно openInputStream.

Не пытайтесь получить “реальный путь” к файлу. На современных Android это плохая практика: файл может лежать в Google Drive, Downloads provider, медиахранилище или другом приложении. Реального filesystem path для вашего приложения может вообще не быть.

Итог: причина не в том, что файла нет, а в неправильном способе чтения. Работайте с Uri через ContentResolver, не через File. Разрешения в manifest для такого выбора обычно не нужны, потому что доступ выдаёт сам системный picker.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно