尝试打开 PDF 时出现 Intent.ACTION_VIEW 的安全异常

SecurityException on Intent.ACTION_VIEW while trying to open PDF

我要求用户使用 ACTION_OPEN_DOCUMENT 选择 PDF 文档。意图 returns 内容 URI。

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.setType("application/pdf");
    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    intent.addCategory(Intent.CATEGORY_OPENABLE);

内容 URI 的格式为 - content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FSample%20PDF.pdf

现在,我希望用户再次访问同一文档 - 稍后,从单独的 activity。所以我写了下面的代码 -

Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
                    pdfIntent.setData(document.getLocalUri());
                    pdfIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    mContext.startActivity(pdfIntent);

但是我收到以下错误 -

java.lang.SecurityException: UID 10197 does not have permission to content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FSample%20PDF.pdf [user 0]; you could obtain access using ACTION_OPEN_DOCUMENT or related APIs

我做错了什么?

What am I doing wrong?

很可能,您的问题出在这里:

I want the user to access the same document again - later on, from a separate activity

请求并收到内容 Uri 的 activity 拥有该内容的权利...但您的应用程序没有其他权利。这包括您当前流程中的其他组件以及未来流程中的任何组件。

如果这是一个单独的activity,但仍在同一个应用程序实例中(即,自从您获得Uri后,您的进程尚未终止),您需要传递权限该内容到单独的 activity。通过 Intent 的 "data" 方面传递 Uri,并像处理 ACTION_VIEW Intent 一样使用 setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)。请参阅 this sample app,其中我使用 FLAG_GRANT_READ_URI_PERMISSION 将权限授予 Service 以便能够阅读内容。

如果您打算保留 Uri 值本身(例如,将其作为字符串存储在数据库中)并在将来使用它,您可以改用 takePersistableUriPermission() on ContentResolver 请求对内容的长期访问。这应该会成功(我不知道您会立即被拒绝访问的任何情况)。在内容发生重大变化(例如用户删除它)之前,您应该可以访问。