4

My app lets the user view some selected images from the Gallery or other locations. I request for the Uri's of images through:

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, PickerFragment.PICK_PHOTO);

And then get the Uri's in onActivityResult (int requestCode, int resultCode, Intent data) and have access to those images to put them in my app's views via:

Uri imageUri= data.getData();

When the app finishes, I save all the Uri's in my database as strings through:

String imageUriString = imageUri.toString();
saveToDB (imageUriString);

However when I re-launch the app and restore all the Uri's from my database via:

String imageUriString = restoreFromDB ();
imageUri = Uri.parse (imageUriString);

the app has no permissions to those Uri's anymore in Android 7.1. I'm accessing the images through:

ContentResolver cr = mContext.getContentResolver();
InputStream is = cr.openInputStream(imageUri);
BitmapFactory.decodeStream(is, null, o);

But receive this exception:

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.impl.MediaContentProvider from ProcessRecord

Is there an elegant and legit way to keep that permission? I tried to read all the docs on permissions, but feel really confused.

Would appreciate if you let me the right direction to learn from.

PS Copying the images into the apps memory while Uri's permission lasts was an option, but I'd like to avoid that. At least to see if it is possible.

PPS I have all permissions granted, like Camera and External Storage write and read.

rommex
  • 763
  • 1
  • 8
  • 21
  • check this link https://stackoverflow.com/questions/37409181/java-lang-securityexception-permission-denial-opening-provider – Sharath kumar Oct 17 '17 at 08:02
  • Store byteArray instead of uri.Uri fails when image is not present in gallery. – Sharath kumar Oct 17 '17 at 08:21
  • @Anonymous, storing is an option, but not desirable. In my case Uri fails even if the image _is_ present in the Gallery – rommex Oct 17 '17 at 08:23
  • Indeed strange as ACTION_PICK does not come with permission flags as far as i know. Earlier only ACTION_GET_CONTENT suffered from this. But i can confirm your problem. Changing to ACTION_GET_CONTENT does not help as you cannot make the permission persisted. – greenapps Oct 17 '17 at 09:28
  • Untested: use ACTION_OPEN_DOCUMENT. Untested. Please try and report. – greenapps Oct 17 '17 at 09:32
  • Indeed ACTION_OPEN_DOCUMENT is the way to go. Be shure to take persistable uri permission. – greenapps Oct 17 '17 at 09:36

1 Answers1

5

So, with significant help of @greenapps and after the testing on the emulator and real devices, the solution is this:

  • use another intent:

    Intent photoPickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);

  • in onActivityResult() secure the persistable permission for Uri which will be intact after the app's re-launch:

    Uri selectedImage = data.getData();

    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) { getContentResolver().takePersistableUriPermission (selectedImage, Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION); }

rommex
  • 763
  • 1
  • 8
  • 21
  • 1
    There are two additional things to worry about: Firstly, if you are persisting the URI as part of your Activity's state, you should check that the URI is still valid before trying to load it (see `ContentResolver.getPersistedUriPermissions()`). Secondly, when you are sure you are finished with the URI, you should rescind your permission using `ContentResolver.releasePersistableUriPermission()`. Lastly, while this logic works for Intent.ACTION_OPEN_DOCUMENT, it does not work if your app receives Intent.ACTION_SEND or Intent.ACTION_SEND_MULTIPLE. – jules Apr 04 '18 at 23:04