-1

I have a PreferenceFragment that implements a custom Preference that I've extended. It launches an intent that returns a selected image from the filesystem. Everything works fine, mostly. The Preference sets the image thumbnail in the preferences view and grabs the display name to set as the preference summary. The URI string persists as it should. However, When the preference screen initializes, it fails to retrieve either the display name or the image resource due to a permissions error.

Unable to open content: content://com.android.providers.downloads.documents/document/125
     java.lang.SecurityException: Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{80311e3 16941:com.companyXXX.appnameXXX/u0a87} (pid=16941, uid=10087) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

I can post the code if anyone wants it. I am sure I have pinpointed the problem, but I am not sure how to add permissions to the ImageView.setImageUri() resource access.

This is not a duplicate of How to ask permission to access gallery on android M.? as I have permissions for the initial file selection. THAT WORKS JUST FINE.

hoping someone out there is familiar with this issue and can provide a solution.

Eric
  • 1
  • 2
  • 1
    See https://stackoverflow.com/questions/39866869/how-to-ask-permission-to-access-gallery-on-android-m/39866945 – EJK Apr 16 '18 at 20:25

1 Answers1

0

It launches an intent that returns a selected image from the filesystem.

Based on that Uri, you are using ACTION_OPEN_DOCUMENT, or perhaps ACTION_GET_CONTENT. Neither are limited to files on the filesystem.

The URI string persists as it should

In general, you should not assume that a Uri is valid indefinitely. They work like URLs do, and while some URLs might work all the time, others are tied to valid user sessions or otherwise will break after some period of time.

i am not sure how to add permissions to the resource access

If you are using ACTION_OPEN_DOCUMENT, you can call takePersistableUriPermissions() on ContentResolver to request durable access to the content identified by the Uri. That Uri may still break (e.g., the user deletes the content), but you will be able to persist the Uri as you are doing.

Otherwise, you have no means of getting durable access to the content, except by making a copy of the content itself.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I am using ACTION_GET_CONTENT, here is the Intent setup: – Eric Apr 16 '18 at 20:38
  • Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE); – Eric Apr 16 '18 at 20:39
  • Is there a more appropriate Action for this implementation? or, can you somehow call takePersistablePermissions() on the intent? – Eric Apr 16 '18 at 20:42
  • Or, is there an altogether better way of storing an image locator as a preference? – Eric Apr 16 '18 at 20:44
  • @Eric: Neither `ACTION_PICK` nor `ACTION_GET_CONTENT` are guaranteed to return a `Uri` that you can use indefinitely, and neither support `takePersistableUriPermissions()`. `takePersistableUriPermissions()` is a method on `ContentResolver`, not `Intent`. The safest thing is for you to copy the image once the user chooses it, and use appropriate labels in your UI (e.g., "import" instead of "link"). Or, [use a file-chooser library](https://android-arsenal.com/tag/35), to limit yourself to files on the filesystem, in which case you can persist the path. – CommonsWare Apr 16 '18 at 20:46
  • Thank you very much I will explore this further and post updates – Eric Apr 16 '18 at 20:56