2

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.

Lucas Meneghin
  • 192
  • 1
  • 12
  • 1
    `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);` You better remove all flags as they are useless. You cannot grant anything. – blackapps Oct 08 '20 at 22:43
  • `.openInputStream(Uri.parse(stringUri + "%3A" + (archiveName + ".png"))));` No. You are trying to build an uri for a file. But this is not the way to obtain such an uri. – blackapps Oct 08 '20 at 22:45
  • `trying to fetch all images from a specific folder` Where? I dont see you doing that. Where are you listing its contents? – blackapps Oct 08 '20 at 22:48
  • @blackapps I did not post the full code, and i also didnt explain it correctly. I'm not trying to fetch all images, but i search within the folder for some specific images (which should be all, but thats not important) I left out a for loop, as it was not important – Lucas Meneghin Oct 09 '20 at 02:10
  • Yes, i am trying to build an uri for a file, so i can turn it into a bitmap. Sorry, but your comments are far from useful, i know i am doing some things wrong, thats why i posted the question – Lucas Meneghin Oct 09 '20 at 02:13
  • 1
    List the content of the folder to begin with. Then you have all uries. – blackapps Oct 09 '20 at 06:53
  • 2
    @blackapps How about explaining how to do it instead of telling us what doesn't work? We, who find this page on Google are not interested in what doesn't work. – Martin Jul 06 '21 at 16:04

1 Answers1

1

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

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I know that some files might not be there, but thats expected. For those, i'll use a placeholder image. I'm going to try it now, thanks. – Lucas Meneghin Oct 09 '20 at 13:21
  • 2
    It ended up being very slow, so i had to rewrite my logic, but it worked. Thank you very much – Lucas Meneghin Oct 09 '20 at 14:09
  • Is there seriously no faster way? How do file explorer programs show files WAY faster than this method? – John Glen Oct 18 '20 at 01:04
  • @JohnGlen: Seasoned developers can work directly with [`DocumentsContract`](https://developer.android.com/reference/android/provider/DocumentsContract) and its nested classes. This API is somewhat cumbersome and poorly documented, which is why I generally steer people towards `DocumentFile` (unoptimized but an easier API). Also, bear in mind that manufacturer-installed file managers might simply be using filesystem APIs, as manufacturer-installed apps can have greater access rights than ordinary apps, if the manufacturer wants. – CommonsWare Oct 18 '20 at 10:55
  • "get rid of those flags, as they are useless in this contex" then how do we should use these flags? – Simon Jun 26 '21 at 00:18
  • @Simon: If you have permissions that you want to grant to others, use `FLAG_GRANT_READ_URI_PERMISSION` and/or `FLAG_GRANT_WRITE_URI_PERMISSION`. You will see this a lot with `ACTION_VIEW`, for example. If you are writing a `DocumentsProvider`, you may have a need for those other two. – CommonsWare Jun 26 '21 at 10:35
  • @CommonsWare, thanks but I was talking about flags like Intent.FLAG_GRANT_PREFIX_URI_PERMISSION – Simon Jun 28 '21 at 00:28
  • @Simon: That too would only be relevant if you have permissions that are you are trying to grant to others. See [the documentation](https://developer.android.com/reference/android/content/Intent?hl=en#FLAG_GRANT_PREFIX_URI_PERMISSION). – CommonsWare Jun 28 '21 at 10:38