使用 ACTION_OPEN_DOCUMENT_TREE 访问外部存储时 Android Q 上的 SecurityException

SecurityException on Android Q for acessing ExternalStorage with ACTION_OPEN_DOCUMENT_TREE

我正在尝试从特定文件夹中获取所有图像以显示在回收站视图中,但无论如何,我都收到了 SecurityException。

我目前正在按照以下方式进行操作:

selecting 文件夹的代码

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);

并获取每个单独的位图(这部分特别是我尝试了许多不同的变体,但结果都相同)

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

我认为问题出在最后一段代码上,但我真的不知道还能尝试什么。

我得到的异常是:

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

我已经使用 getPersistedUriPermissions 检索了持久化权限,它包含以下 uri:

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

我几乎可以肯定我不能像我一样手动附加文件名,但我不知道我必须做什么。

我读过其他帖子,有很多不同的答案,但 none 有效,我尝试了几乎所有我能找到的东西。

感谢任何帮助,谢谢。

已编辑:

问题是我只希望用户 select 文件夹,而不是所有图像,然后我将在文件夹中搜索我想要的图像,在我省略的循环中,因为它不是一部分的问题。我只想知道如何打开我有权限的文件夹中的特定文件。

Code for selecting folder

正如 blackapps 所指出的,去掉这些标志,因为它们在这种情况下是无用的。

I think the problem is on the last bit of code

正确。您无法手动创建有效文档 Uri 值。

but i really dont know what else to try

你要的不靠谱。您正在假设树中文档的显示名称可能与实际情况不符。但是,如果您愿意忍受兼容性问题,您可以这样做:

第 1 步:调用 DocumentFile.fromTreeUri(),传入您从 onActivityResult() 获得的树 Uri,为树 [=25= 提供 DocumentFile ]

第 2 步:在那个 DocumentFile 上调用 listFiles() 来为您提供一个 DocumentFile 对象数组,表示该树根

的内容

第 3 步:使用 getName()isFile() 将该数组过滤为与所需命名方案匹配的子集

第 4 步:对于匹配的文件,调用 getUri() 获取这些文件的 Uri,您可以将其传递给您最喜欢的 image-loading 图书馆