6

I have these as my permissions:

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

I'm getting a permission denial error here on the openInputStream line:

if(bgUri != null && !bgUri.isEmpty()) {
            try {
                InputStream inputStream = context.getContentResolver().openInputStream(Uri.parse(bgUri));   // <-- error
                return Drawable.createFromStream(inputStream, bgUri);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

I first load my image with

@Override
public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
    if (requestCode == SELECT_PHOTO && resultCode == Activity.RESULT_OK) {
        try {
            final Uri imageUri = imageReturnedIntent.getData();

            final int takeFlags = imageReturnedIntent.getFlags()
                    & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            // Check for the freshest data.
            mContext.getContentResolver().takePersistableUriPermission(imageUri, takeFlags);

then save the image uri:

            String backgroundURI = imageUri.toString();
            int backgroundID = 0;
            mStore.backgroundImageURI = backgroundURI;
            mStore.backgroundImageNumber= backgroundID;
            mStore.save();

Stack trace:

﹕ FATAL EXCEPTION: main
Process: com.myapp.pocketandroid, PID: 1284
java.lang.RuntimeException: Unable to resume activity {com.myapp.pocketandroid/com.myapp.pocketandroid.MainActivity}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{52946004 1284:com.myapp.pocketandroid/u0a60} (pid=1284, uid=10060) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2774)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2803)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2238)
        at android.app.ActivityThread.access$800(ActivityThread.java:135)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{52946004 1284:com.myapp.pocketandroid/u0a60} (pid=1284, uid=10060) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
        at android.os.Parcel.readException(Parcel.java:1465)
        at android.os.Parcel.readException(Parcel.java:1419)
        at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2848)
        at android.app.ActivityThread.acquireProvider(ActivityThread.java:4399)
        at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2208)
        at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1425)
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1047)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:904)
        at android.content.ContentResolver.openInputStream(ContentResolver.java:629)
        at com.myapp.pocketandroid.Utils.BackgroundImageManager.background(BackgroundImageManager.java:29)
        at com.myapp.pocketandroid.BaseActivity.setBackground(BaseActivity.java:83)
        at com.myapp.pocketandroid.BaseActivity.onResume(BaseActivity.java:44)

Why do I get the MediaDocumentsProvider permission crash when I resume my activity and attempt to load the URI? I thought that by taking the permission I keep the permission permanently.

quantumpotato
  • 9,637
  • 14
  • 70
  • 146
  • Please post your code that "attempt to load the URI" along with the complete stack trace. – CommonsWare Sep 09 '15 at 18:46
  • 1
    @CommonsWare the crash is in the first block of code. I added a stack trace. – quantumpotato Sep 09 '15 at 18:55
  • What are you doing between calling `takePersistableUriPermission()` and `openInputStream()`? You wrote that you get this crash when you "resume [your] activity". Do you mean this literally (i.e., it is the same activity instance as you used with `takePersistableUriPermission()` and is just coming back to the foreground)? Or do you mean something else? – CommonsWare Sep 09 '15 at 19:06
  • I'm selecting a background image, saving it, it works fine. I close out the application, restart the device. On resuming activity, BaseActivity sets a background. It does this by looking up the bgURI from a database model, which is called with InputStream inputStream = context.getContentResolver().openInputStream(Uri.parse(bgUri)); . >> crashes – quantumpotato Sep 09 '15 at 19:38
  • 1
    "I'm selecting a background image" -- via `ACTION_OPEN_DOCUMENT`? I would assume so, given the exception details. If yes, then I have no idea why this isn't working for you. A bunch of people seem to run into this problem, and I haven't played with `takePersistableUriPermission()` yet, but it's clearly something I need to work on... – CommonsWare Sep 09 '15 at 19:46
  • Yes, I'm following the accepted answers for other SO questions.. – quantumpotato Sep 09 '15 at 20:14
  • Is it not because you are compiling the app with SDK 23 and the device is also sdk 23? Because then you need to check if the permission has been granted, and if not, prompt for the permission. – riggaroo Sep 16 '15 at 10:16
  • Then device is earlier than 23, it's API level 19 – quantumpotato Sep 16 '15 at 13:15

1 Answers1

1

It appears you are using the "get freshest data" from here and the SELECT_PHOTO from here. Correct? Assuming that's the case ---

The SELECT_PHOTO example uses an ACTION_PICK to choose the photo. Quoting:

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);  

However, as pointed out, Intent.ACTION_PICK has no guarantees about persistability. Instead, use Intent.ACTION_OPEN_DOCUMENT. From the API docs, applicable to API 19 or higher:

All selected documents are returned to the calling application with persistable read and write permission grants. If you want to maintain access to the documents across device reboots, you need to explicitly take the persistable permissions using takePersistableUriPermission(Uri, int).

Try

Intent photoPickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);  

and see how you do.

Community
  • 1
  • 1
cxw
  • 16,685
  • 2
  • 45
  • 81