Запись файлов в android api Q, которые сохранятся при удалении приложения

Хочу сделать фичу резервного копирования некоторых настроек приложения в файл, чтобы после удаления или установки на новое устройство у пользователя была возможность восстановить свой прогресс из файла лежащего в памяти устройства.

Проблема в том что привычный getExternalStorageDirectory() в android 10 стал deprecated, и использовать его не получается. Все, что я нашел записывает файлы в папки, которые удаляются вместе с приложением. Да, с этими файлами можно взаимодействовать через проводник, но это будет неудобно каждому пользователю.

Есть ли способ записи файла в папку, которая не удалится вместе с приложением?


Ответы (1 шт):

Автор решения: Barmaley

Да, можно. Для этого вам надо получить пермишен на каталог, куда вы собираетесь писать. В терминах Scoped Storage делается это так:

1)Сначала запрашиваем пермишен на чтение запись, для чего запускаем Intent:

 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION  |
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION  |
                    Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
            startActivityForResult(intent, REQUEST_FOLDER);

2)При запуске Intent у юзера будет запрошен каталог и разрешение на чтение/запись, после выбора юзером каталога, выстреливает onActivityResult(), который надо обработать примерно так:

if(requestCode==REQUEST_FOLDER && resultCode==RESULT_OK && intent!=null && intent.getData()!=null) {
        //retain folder read/write permissions
        ContentResolver contentResolver = this.getContext().getContentResolver();
        int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION |
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        Uri folderUri = intent.getData(); //uri каталога, в который будет разрешена запись
        contentResolver.takePersistableUriPermission(forlderUri, takeFlags);
}

3)Далее берем folderUri пишем туда все что хотим, примерно так:

DocumentFile pickedDir = DocumentFile.fromTreeUri(context, folderUri);
DocumentFile myFile = pickedDir.createFile("*/txt", "myfilename.txt"); 
//пишем в myFile
→ Ссылка