Permission for an image from Gallery is lost after

2019-06-05 06:48发布

问题:

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.

回答1:

Refer answer here

Open a Dialog using the code below:

 ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    1);

Get the Activity result as below:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {

          // If request is cancelled, the result arrays are empty.
          if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.          
            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

More info: https://developer.android.com/training/permissions/requesting.html



回答2:

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