Search code examples
androiduriandroid-10.0securityexceptiondocuments-provider

SecurityException on Android Q for acessing ExternalStorage with ACTION_OPEN_DOCUMENT_TREE


I'm trying to fetch all images from a specific folder for displaying in a recycler view, but no matter what, i get a SecurityException.

I'm currently doing it the following way:

Code for selecting folder

Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
            | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    lastRequest = REQUEST_IMAGENS;
    startActivityForResult(i, REQUEST_IMAGENS);

onActivityResult

getContentResolver().takePersistableUriPermission(data.getData(),data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION |
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

and for fetching each individual bitmap (this part specifically i tried many different variations, but all with same result)

BitmapFactory.decodeStream(xContext.getContentResolver().openInputStream(Uri.parse(stringUri + "%3A" + (archiveName + ".png"))));

I think the problem is on the last bit of code, but i really dont know what else to try.

The exception i get is:

java.lang.SecurityException: Permission Denial: reading com.android.externalstorage.ExternalStorageProvider uri content://com.android.externalstorage.documents/tree/primary%3ADownload%2FSaurus%20-%20Cadastro%20-%20Imagens%3A2171.png from pid=13239, uid=10425 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

I've retrieved the persisted permissions with getPersistedUriPermissions and it contains the following uri:

content://com.android.externalstorage.documents/tree/primary%3ADownload%2FSaurus%20-%20Cadastro%20-%20Imagens

I'm almost certan i cant manually append the file name like i did, but i dont know what i have to do instead.

I've read other posts and there are lots of different answers, but none worked and i tried almost everything i could find.

Any help is appreciated, thanks.

Edited:

The problem is i only want the user to select the folder, not all the images, and then i will search the images i want within the folder, in a loop that i omitted because its not part of the problem. All i want to know is how to open a specific file within a folder i have permissions.


Solution

  • Code for selecting folder

    As blackapps noted, get rid of those flags, as they are useless in this context.

    I think the problem is on the last bit of code

    Correct. You cannot create valid document Uri values manually.

    but i really dont know what else to try

    What you want is not reliable. You are making assumptions about display names of documents in a tree that may not match reality. But, if you are willing to live with compatibility problems, you can do this:

    Step #1: Call DocumentFile.fromTreeUri(), passing in the tree Uri that you got from onActivityResult() to give you a DocumentFile for the tree

    Step #2: Call listFiles() on that DocumentFile to give you an array of DocumentFile objects representing the contents of that tree root

    Step #3: Use getName() and isFile() to filter that array to the subset that match your desired naming scheme

    Step #4: For those that match, call getUri() to get the Uri for those documents, which you can pass to your favorite image-loading library