Search code examples
androidimagepermissionsgallery

Permission for an image from Gallery is lost after re-launch


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.


Solution

  • 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);
      }