Android хранит и повторно использует полученные URI

Мое приложение собирает мультимедиа с помощью намерения ACTION_PICK, чтобы получить android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI

тип контента. Когда я получаю URI нужного мне контента, он отлично работает, и я могу просмотреть его с помощью:

val intent = Intent(Intent.ACTION_VIEW, myURI)
intent.setDataAndType(myURI,contentResolver.getType(myURI))
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION)
startActivity(intent)

Я сохраняю Uri с помощью метода Uri.toString, и как только я закрываю действие и открываю его снова, я получаю следующую ошибку:

java.lang.SecurityException: UID 10315 does not have permission to content://com.miui.gallery.open/raw/%2Fstorage%2Femulated%2F0%2FDCIM%2FCamera%2FVID_20200814_214253.mp4 [user 0]

и еще ниже:

Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.uri.UriGrantsManagerService.checkGrantUriPermission(UriGrantsManagerService.java:1192)
    at com.android.server.uri.UriGrantsManagerService.checkGrantUriPermissionFromIntent(UriGrantsManagerService.java:579)
    at com.android.server.uri.UriGrantsManagerService.grantUriPermissionFromIntent(UriGrantsManagerService.java:618)
    at com.android.server.uri.UriGrantsManagerService$LocalService.grantUriPermissionFromIntent(UriGrantsManagerService.java:1392)

В идеале я бы получил путь к файлу носителя и сгенерировал URI из файла через fileProvider, но я не нашел способа получить абсолютный путь из ContentURI.

Прочитайте https://commonsware.com/blog/2016/08/10/uri-access-lifetime-shorter-than-you-might-think.html, который лучше объясняет, что происходит, так как я могу повторно использовать или хранить файл, который я получил через его URI? Могу ли я каким-то образом получить путь к файлу вместо URI?


person sgtpotatoe    schedule 18.08.2020    source источник


Ответы (1)


Я храню Uri с помощью метода Uri.toString

Это не сработает. Ваши права на контент, полученный от ACTION_PICK, составляют очень недолго. (примечание: эта ссылка относится к более новой версии моего сообщения в блоге, на которое вы ссылались в вопросе)

В идеале я бы получил путь к файлу носителя

Это тоже не сработает. Для ACTION_PICK или подобных действий не требуется возвращать что-либо, относящееся к файловой системе, не говоря уже о каком-либо файле, к которому вы можете получить прямой доступ. В вашем конкретном случае MediaStore имеет больший доступ, чем вы, поэтому вещи, которые вы найдете в MediaStore, могут быть недоступны, даже если вы запросите полуустаревший столбец DATA, чтобы попытаться найти путь. Кроме того, реализация ACTION_PICK, которую выбирает пользователь, может в любом случае не возвращать MediaStore Uri.

Если вам нужно иметь возможность выбрать фрагмент контента, сохранить его Uri и использовать этот Uri для работы с контентом позже, вам необходимо:

  • Используйте ACTION_OPEN_DOCUMENT вместо ACTION_PICK

  • Позвоните takePersistableUriPermissions() по номеру ContentResolver, передав полученный Uri

Теперь у вас есть долгосрочный доступ к содержимому... при условии, что пользователь не сделает что-то радикальное, например, не удалит его. ????

person CommonsWare    schedule 18.08.2020
comment
Не собираюсь лгать, я скрестил пальцы, что CommonsWare, автор статьи, которая лучше всего описывает мою ситуацию, ответит, и вот он! - Это определенно работает, пользователям придется адаптироваться к использованию documentProvider для выбора мультимедиа, но, похоже, это единственный рабочий способ. - person sgtpotatoe; 19.08.2020