1

I have am creating an app that will allow a user to pick a photo from the gallery. Once they click on the photo I am saving the uri to my room db. When I try to go back and view the photo in my app I get this error

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dayaramo.wearyourcloset/com.dayaramo.wearyourcloset.EditItem}: java.lang.SecurityException: No persistable permission grants found for UID 10492 and Uri content://com.android.externalstorage.documents/document/primary:DCIM/Camera/20200508_145429.jpg

I know that you are supposed to use the takePersistableUriPermissions but it seems to be ignoring that.

The code to pick and save the image uri from the gallery is

void imageChooser() {

        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);

    }
  @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == SELECT_PICTURE && resultCode == RESULT_OK)  {

                Uri selectedImageUri = data.getData();
                if (null != selectedImageUri) {
                    // update the preview image in the layout
                    pictureResult.setImageURI(selectedImageUri);
                }
            }
    }

The code to view the photo again is

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*");
this.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
pictureResult.setImageURI(uri);

Is it best practice to copy the photo from the shared storage into the apps internal storage? I don't care if the photo get's moved or deleted which is why I just want to use the URI instead of copying it.

2 Answers2

1

The code to view the photo again is

Other than perhaps the last line, the rest of that code snippet is either incorrect or unused.

Instead, call takePersistableUriPermission() inside onActivityResult(), so you request durable access right away:

  @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
      if (requestCode == SELECT_PICTURE && resultCode == RESULT_OK)  {

                Uri selectedImageUri = data.getData();
                if (null != selectedImageUri) {
                    // update the preview image in the layout
                    pictureResult.setImageURI(selectedImageUri);
                    getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            }
    }

Also, only ask for write permission if you are intending to replace the image at that Uri, and bear in mind that you cannot always get write access.

And, as blackapps noted, you need to switch from ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks for this. I put the ```takePersistableUriPermission()``` inside the ```onActivityResult()``` but now when I try to view the picture it again it takes me back to the directory where the picture is and I have to reselect it. – olivia.dayaram Feb 04 '22 at 15:23
  • @olivia.dayaram: "when I try to view the picture it again it takes me back to the directory where the picture is and I have to reselect it" -- sorry, but I do not know what "it" is. – CommonsWare Feb 04 '22 at 15:24
  • Reselect the picture. The picture hasn't been moved or deleted and I'm expecting that when I go to view the picture again I shouldn't have to reselect the picture, the picture should be in the imageview – olivia.dayaram Feb 04 '22 at 15:45
  • @olivia.dayaram: "I shouldn't have to reselect the picture" -- then get rid of the code that you wrote that is forcing you to reselect the picture. For example, in your latter code snippet in your question, get rid of all but the last line. – CommonsWare Feb 04 '22 at 15:54
  • I think I'm missing something there. I put that code inside the ```onActivityResult()``` and removed the ```takePersistableURIPermission()``` out of that code snipped so now it looks like this ```Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(Intent.createChooser(intent,"Select Picture"),GALLERY_REQUEST);``` Now it's asking me to reselect the photo. If I try to directly set the uri it says I don't have permissions. I'm not sure which part of my code is forcing me to reselect the photo – olivia.dayaram Feb 04 '22 at 16:09
  • Thank you @commonsware! This post helped me understand: ask for the durable access right away with getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); – Lucy Jan 13 '23 at 04:15
1

For Intent.ACTION_GET_CONTENT you cannot take persistable permission.

Use ACTION_OPEN_DOCUMENT instead.

Take them in onActivityResult as you have been said already.

blackapps
  • 8,011
  • 2
  • 11
  • 25