'Having trouble implementing ACTION_OPEN_DOCUMENT to my project

I have AddActivity, which lets you get the URI from either a picture you can take from the camera, or an image that you can select from the gallery. Then you can go to DetailsActivity to view the image. I have it working right now until you restart the device. After you restart and try to go to DetailsActivity for that image, this is the error:

Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{3a5e86d 2915:jeremy.com.wineofmine/u0a321} (pid=2915, uid=10321) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

I went to the "Open Files Using Storage Access Framework" Android Development page and read up on the Persist Permissions section. I'm having trouble applying it to my project though.

I think the main thing I don't understand is that it looks like you need to call an intent (in my case inside the DetailsActivity), but I don't even have an intent there.

Here is the intent that lets you pick the gallery image. This is in AddActivity:

Intent intentGallery = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intentGallery.addCategory(Intent.CATEGORY_OPENABLE);
            intentGallery.setType("image/*");
            intentGallery.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intentGallery.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            startActivityForResult(intentGallery, SELECT_IMAGE);

In the DetailsActivity, this is where it actually crashes:

imageURI = Uri.parse(cursor.getString(cursor.getColumnIndexOrThrow(WineContract.WineEntry.COLUMN_WINE_IMAGE)));

bitmap = null;
    try {
        //If the cursor does not have anything in the image column, set the image to null, with a height so the textviews look decent
        if (cursor.isNull(cursor.getColumnIndexOrThrow(WineContract.WineEntry.COLUMN_WINE_IMAGE))){
            mFullImage.setImageBitmap(null);
            mFullImage.setMaxHeight(300);
        }else{
            //remake the bitmap from the URI in the image column
      //********This next line is where the program crashes**********
            bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageURI);
            mFullImage.setImageBitmap(bitmap);

        }

Could I get some help with figuring out how to apply this to my project?



Solution 1:[1]

In onActivityResult(), call takePersistableUriPermission() on a ContentResolver, passing in the Uri that you got along with the mode flag(s) that indicate what access you want (read, write, both).

Solution 2:[2]

a bit late but... We need to provide persistent Uri permission. Instead of doing it on onActivityResult as oppose to prior answers, I prefer to add it as a flag:

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).also {
    it.addCategory(Intent.CATEGORY_OPENABLE)
    it.type = "image/*"
    it.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
    it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}

Also, a note worth mentioning, persistent permission is available only to Intent.ACTION_OPEN_DOCUMENT and NOT Intent.ACTION_GET_DOCUMENT whereas later one is like a one-time thing.

Solution 3:[3]

The permission denial issue needs to be dealt with the first time you receive a URI. If you use registerForActivityResult() instead of startActivityForResult()

    // Kotlin
    private val pickImage = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //  you will get result here in result.data
            val uri = result.data?.data!!
            requireActivity().contentResolver.takePersistableUriPermission(
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
            )
            // Do something else with the URI. E.g, save the URI as a string in the database
        }
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 CommonsWare
Solution 2
Solution 3 Booo