【问题标题】:Android open InputStream from relative uri to ACTION_OPEN_DOCUMENT?Android从相对uri打开InputStream到ACTION_OPEN_DOCUMENT?
【发布时间】:2019-04-14 05:19:00
【问题描述】:

我正在尝试在 android 4.4(api 级别 19)中打开多个相对于 json 配置文件的文件, 我用过

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType({mime});
this.startActivityForResult(intent, {code});

让用户找到配置文件,并从那里打开多个我知道配置文件路径的文件。

但我明白了

Caused by: java.lang.SecurityException: 
Permission Denial: reading com.android.providers.downloads.DownloadStorageProvider
uri content://com.android.providers.downloads.documents/document/raw:/storage/emulated/0/Download/{relative file}
requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

我不想使用用户界面打开其他文件,所以我尝试添加以下权限但没有得到任何结果

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

我宁愿将文件分开,而不是放在 blob 或 zip 文件中

【问题讨论】:

  • 你给READ_EXTERNAL_STORAGE和MANAGE_DOCUMENTS设置运行时权限了吗?
  • 我刚刚尝试过,我可以获得 READ_EXTERNAL_STORAGE,但不能获得 MANAGE_DOCUMENTS,但仍然会获得 Permission denial。我使用 minSdkVersion 19,所以尝试使用 ActivityCompat.requestPermissions
  • “我正在尝试打开多个文件”——您的代码实际上与打开文件无关。如果您需要将用户限制为您的应用能够直接访问的文件系统上的文件,请使用a file chooser library,而不是像ACTION_OPEN_DOCUMENT 这样的系统Intent

标签: android relative-path permission-denied android-contentresolver storage-access-framework


【解决方案1】:

ACTION_OPEN_DOCUMENT 仅允许您访问用户选择的确切文件(或文件,如果您使用 EXTRA_ALLOW_MULTIPLE)。

您可以使用ACTION_OPEN_DOCUMENT_TREE 允许用户选择一个文件夹 - 然后您将可以访问该文件夹(及其子文件夹)中的所有文件。

【讨论】:

  • ACTION_OPEN_DOCUMENT_TREE 是在 API 级别 21 中添加的,忘记指定了,但我使用的是 minSdkVersion 19,所以我不能使用它,我想我将只使用 zip 文件:'(
  • 正确,没有等效的 pre-API 21。
【解决方案2】:

如果您需要让用户从文件选择器中选择多个文件,您可以执行以下操作:

这是我的应用程序的一部分,您可以根据需要进行调整。这从 API 18 开始工作

private void openFileChooser() {
    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
    i.setType("*/*");
    i.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
    i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    startActivityForResult(i, REQUEST_CODE_DOC_ALL_FILES);
}

那么这里是你如何获得选定的 Uris:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

if (requestCode == REQUEST_CODE_DOC_ALL_FILES && resultCode == Activity.RESULT_OK) {

        if (data == null || (data.getData() == null && data.getClipData() == null)) {
            Toast.makeText(getContext(), R.string.invalid_source, Toast.LENGTH_SHORT).show();
            return;
        }


        //get result after user action (selecting files) and transform it into array of Uris
        Uri[] uriPaths;
        if (data.getData() != null) { // only one uri was selected by user
            uriPaths = new Uri[1];
            uriPaths[0] = data.getData();
        } else if (data.getClipData() != null) {
            int selectedCount = data.getClipData().getItemCount();
            uriPaths = new Uri[selectedCount];
            for (int i = 0; i < selectedCount; i++) {
                uriPaths[i] = data.getClipData().getItemAt(i).getUri();
            }
        } 
}

【讨论】:

    猜你喜欢
    • 2011-01-27
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 2017-05-24
    • 2014-06-28
    • 2023-02-21
    相关资源
    最近更新 更多