12

I am trying to allow the user to access his photo library to get a profile picture, and that save that profile picture to SharedPreferences. I also have a navbar that gets this picture from SharedPreferences

I am getting the following error:

java.lang.SecurityException: 
Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord
{a601c1c 3379:com.example.foo.finalapp/u0a60} (pid=3379, uid=10060) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS

Here is the code for getting the picture:

MainActivity

       ImageView prof_pic = (ImageView) header.findViewById(R.id.profPic);
        pref = getSharedPreferences(Profile.pref_filename, 0);
        String uri = pref.getString("target_uri", "");
        TextView tv_name = (TextView) header.findViewById(R.id.tv_name);
        String name = pref.getString("name", "");
        if(!uri.equals("")) {
            Uri urii = Uri.parse(uri);
            try {
                Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(urii));
                tv_name.setText(name);
                prof_pic.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {

            }
        }
        else {
            prof_pic.setImageResource(R.drawable.ic_android_black_24dp);
        }
    }

profile_pic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                Intent intent = new Intent(Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, 0);
                */
                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) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == KITKAT_VALUE) {
            if (resultCode == RESULT_OK) {
                targetUri = data.getData();
                //Bitmap bitmap;
                try {
                    bitmap = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(targetUri));
                /*
                SharedPreferences.Editor edit = pref.edit();
                edit.putString("target_uri", targetUri.toString());
                edit.apply();
                */
                    sTargetUri = targetUri.toString();
                    profile_pic.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

Here is my manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.finalapp">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".JobViewActivity"></activity>
    </application>

</manifest>
Jeremy Fisher
  • 2,510
  • 7
  • 30
  • 59
  • 1
    You do not show how you get that `Uri`. However, at least in this situation, [you do not have long-term access to the content that it identifies](https://commonsware.com/blog/2016/08/10/uri-access-lifetime-shorter-than-you-might-think.html). – CommonsWare Apr 15 '17 at 20:09
  • Does your app request the permission? Try manually grant required permission, Settings > App > YourApp > Permissions (API 23 and above) – esQmo_ Apr 15 '17 at 20:21
  • @esQmo It request it in the manifest – Jeremy Fisher Apr 15 '17 at 21:24
  • It is declared in the manifest, but did the app ask permission on runtime? (the first time launched)? – esQmo_ Apr 15 '17 at 21:26
  • 1
    No it does not ask on runtime. It crashes with the MANAGE_DOCUMENTS message – Jeremy Fisher Apr 15 '17 at 21:27
  • Are you getting the error on KitKat only? – esQmo_ Apr 15 '17 at 21:29
  • I'm running on API 23 but the app needs to work for all API <= and > 19 – Jeremy Fisher Apr 15 '17 at 21:29
  • You should read answers from this question, there is a workaround that may work for you: http://stackoverflow.com/q/19837358/5374691 – esQmo_ Apr 15 '17 at 21:34
  • I've already looked at that question – Jeremy Fisher Apr 15 '17 at 21:35
  • You should also have a look here: https://developer.android.com/guide/topics/providers/document-provider.html#client – esQmo_ Apr 15 '17 at 22:13
  • Does this answer your question? [Android - file provider - permission denial](https://stackoverflow.com/questions/24467696/android-file-provider-permission-denial) – Sam Jul 26 '22 at 23:43

3 Answers3

4
public static final int GALLERY_INTENT_CALLED = 1;
    public static final int GALLERY_KITKAT_INTENT_CALLED = 2;

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



public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                Uri originalUri = null;
                if (Build.VERSION.SDK_INT < 19) {
                    originalUri = data.getData();
                } else {
                    originalUri = data.getData();
                    final int takeFlags = data.getFlags()
                            & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

                    try {
                        getActivity().getContentResolver().takePersistableUriPermission(originalUri, takeFlags);
                    }
                    catch (SecurityException e){
                        e.printStackTrace();
                    }
                }
                try {
                    bitmap = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(originalUri));
...
Jeremy Fisher
  • 2,510
  • 7
  • 30
  • 59
  • 21
    Please add a description how you fixed the problem. – Prajwol Onta Oct 18 '19 at 10:16
  • if this content is a part of your question please use the edit button under the original question and edit it. if it's an answer, Please read [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). While this code block may answer the OP's question, this answer would be much more useful if you explain how this code is different from the code in the question, what you've changed, why you've changed it and why that solves the problem without introducing others. – Saeed Zhiany Jul 23 '22 at 03:13
2

In my case, the image resource file in my device was removed and the android system could not find the correct path. Clearing my room database and running the app again solved the issue.

Oleohi
  • 86
  • 1
  • 5
2

Once first URI is opened with success run :

getContentResolver().takePersistableUriPermission(myURI, (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION));

In order to save read and write permissions.

J.Jacobs
  • 703
  • 6
  • 17