8

I found this issue only in some devices when trying to pick the picture for the profile image. While checking in the emulator these issue are not seen but on live version of the app this issues are facing by this users. Screenshot captured from the firebase crash report. Please help me to figure out the issue.

AndroidMenifest.xml

...
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
...

SomeActivity.java

private void pickProfilePictureTask() {

    Intent intent = null;
    if (Build.VERSION.SDK_INT > 19) {

        intent = new Intent(Intent.ACTION_OPEN_DOCUMENT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.addCategory(Intent.CATEGORY_OPENABLE);

    } else {

        intent = new Intent(Intent.ACTION_GET_CONTENT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    }

    intent.setType("image/*");
    startActivityForResult(intent, IMAGE_PICKER_REQUEST);


}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == IMAGE_PICKER_REQUEST && resultCode == Activity.RESULT_OK) {


        if (data != null) {
            /**Getting bitmap
             *
             * InputStream inputStream = getActivity().getContentResolver().openInputStream(data.getData());
             * Bitmap userPicBitmap = BitmapFactory.decodeStream(inputStream);
             */
            File file = new File(getFileNameFromURI(data.getData()));
            String imageName = file.getPath();
            uploadProfilePicture.setText(imageName);
            userProfilePicUri = data.getData() + "";

        }


    }
}

private String getFileNameFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) {
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

ERROR in Android 5.1.1 Exception java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image%3A6617 from pid=19207, uid=10260 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()

enter image description here

ERROR in Android 8.0.0 Exception java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{5c1039e 5061:com.mobotechnology.cvmaker/u0a219} (pid=5061, uid=10219) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

enter image description here

jazzbpn
  • 6,441
  • 16
  • 63
  • 99
  • 1
    Please provide a [mcve] showing the code that is triggering these crashes. My guess is that you are trying to persist a `Uri` and use it later, and that only works if you use the Storage Access Framework (`ACTION_OPEN_DOCUMENT`, etc.) and take persistable `Uri` permissions. – CommonsWare Jan 10 '18 at 12:43
  • Do you mind elaborating the answer? @CommonsWare – jazzbpn Jan 10 '18 at 12:54
  • Yeah, I am trying to persist the Uri and use that Uri later. But I didn't get your answer. So, do you mind elaborating it? @CommonsWare – jazzbpn Jan 10 '18 at 13:04

2 Answers2

22

I am trying to persist the Uri and use that Uri later

That will work for a Uri with a file scheme. It will not work for most Uri values with a content scheme. Those are more akin to an HTTP URL to an authenticated Web site — the URL is good while your session is alive but is useless afterwards.

If you obtain the Uri via ACTION_OPEN_DOCUMENT, ACTION_CREATE_DOCUMENT, or ACTION_OPEN_DOCUMENT_TREE, and you call takePersistableUriPermission() on ContentResolver supplying the Uri, then you can safely persist that Uri. You will have access to the content indefinitely, until the user revokes access or the content significantly changes (e.g., is deleted) such that its Uri is no longer valid.

Any other content Uri (e.g., ACTION_GET_CONTENT) is only good for a very short time. Your only option here is to copy the content to some file that you control (e.g., in getCacheDir()) and save the path to that file.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    I'm having a really hard time understand this permission model. Getting "No persistable permission grants found for UID". when calling takePersistableUriPermission() – frankelot Jun 28 '21 at 18:28
  • 1
    @frankelot: Are you using the `Uri` delivered to you by `onActivityResult()` or the contract? If you are, then presumably the documents provider is not offering persistable permission grants -- that's not a requirement. Where are you getting the document from? – CommonsWare Jun 28 '21 at 18:38
  • 1
    Thanks for the reply CommonsWare. Totally my bad, I was using ACTION_GET_CONTENT, switching to ACTION_OPEN_DOCUMENT fixed the issue – frankelot Jun 30 '21 at 08:48
3

Try this:

public static final int KITKAT_VALUE = 1002;

Intent intent;

if (Build.VERSION.SDK_INT < 19) {
    intent = new Intent();
    intent.setAction(Intent.ACTION_GET_CONTENT);
    intent.setType("*/*");
    startActivityForResult(intent, KITKAT_VALUE);
} else {
    intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("*/*");
    startActivityForResult(intent, KITKAT_VALUE);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == KITKAT_VALUE ) {
        if (resultCode == Activity.RESULT_OK) {
            // do something here
        }
    }
}
Deep Lathia
  • 750
  • 7
  • 18