Пишу небольшое приложение в Android Studio, как и многие столкнулся с типовой задачей — диалог выбора файла и его загрузка.
Ясно, что устройство уже имеет какой то файловый менеджер, и писать свой диалог — хоть и интересно, но является и тратой времени, а в будущем еще и доп. компонентом, требующим поддержки.
Используем Activity Result APIs для вызова существующего файл менеджера, и допустим, что в нашем activity (MainActivity) есть какая то кнопка запускающая этот диалог.
Тогда код может выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class MainActivity : AppCompatActivity() { val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> if (result.resultCode == Activity.RESULT_OK) { // открываем поток на чтение по полученному URI val intent = result.data val myFile = getContentResolver().openInputStream(intent?.data!!) if (myFile != null) { // читаем данные val content = myFile.bufferedReader().readText() // демонстрируем имя файла и объем прочитанных данных Toast .makeText(this, "File %s, Length %d bytes".format(intent?.data!!.path, content.length), Toast.LENGTH_LONG) .show() } } } fun onActionClick(view: View) { // настраиваем фильтры intent val intent = Intent() .setType("*/*") .setAction(Intent.ACTION_GET_CONTENT) // запускаем контракт startForResult.launch(intent) } } |
В начале вы создаёте и регистрируете т.н. контракт, а при нажатии кнопки вызываете его с нужным intent фильтром.
В обработчике результата я открываю поток на чтение, используя переданный URI. Всё содержимое файла я читаю в переменную content.