Как получить доступ к аудио файлу по Uri android?

Приложение плеер для android.

С помощью интента Intent.ACTION_GET_CONTENT пользователь находит в памяти телефона аудиофайл. После этого запоминается Uri аудиофайла: data.getData()
Когда надо проиграть файл, создаётся Mediaplayer:

player = MediaPlayer.create(getContext(),sourceUri);
player.setOnCompletionListener(this);

Всё хорошо создаётся, проигрывается, работает. При закрытии программы Uri сохраняется в бд с помощью sourceUri.toString();. При повторном открытии пути загружаются через Uri.parse(). Загружаются правильно, все как и были.
Но при попытке проиграть песню по этому Uri приложение вылетает: MediaPlayer.create(getContext(),sourceUri); возвращает null. Похоже, что нет прав доступа. Причём если после запуска загрузить хоть 1 песню из памяти (новую, старую не важно), то все Uri, загруженные из бд начинают "работать" и прав им уже хватает.

Что сделать, чтобы прав хватало при запуске сразу?


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

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

Это не баг а фича. Так работает scoped storage - чтобы получить доступ к файлу во внешнем хранилище обязательно нужно участие юзера через Intent.ACTION_GET_CONTENT/ACTION_OPEN_DOCUMENT, если функционал вашего приложения устроен так, что требуется возможность повторного прослушивания без вмешательства юзера, то надо копировать файл себе через:

Uri uri = intent.getData();
InputStream is = context.getContentResolver().openInputStream(uri);
→ Ссылка
Автор решения: Sergei Buvaka

Вы можете удержать права доступа на полученную URI так:

val contentResolver = applicationContext.contentResolver

val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or
        Intent.FLAG_GRANT_WRITE_URI_PERMISSION
// Check for the freshest data.
contentResolver.takePersistableUriPermission(uri, takeFlags)

Более подробно в документации.

→ Ссылка