查看来自内容提供商 URI 的意图?

发布于 2024-10-15 17:13:59 字数 2348 浏览 2 评论 0原文

我有一些保护某些敏感数据的要求。数据从 URL 以 PDF 形式下载,并使用以下代码保存为应用程序私有文件:

public File downloadPDF(final Context fileContext, Uri reportUri, final String fileName)
{
    try
    {
        HttpGet get = new HttpGet(reportUri.toString());

        File file = httpClient.execute(get, new ResponseHandler<File>()
        {
            @Override
            public File handleResponse(HttpResponse response) throws ClientProtocolException, IOException
            {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
                {
                    response.getEntity().writeTo(fileContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE));
                    return fileContext.getFileStreamPath(fileName);
                }
                return null;
            }
        });

        return file;
    }
    catch (IOException e)
    {
        Log.e(TAG, "Unable to download report.", e);
    }

    return null;
}

现在,我想做的是将其更改为使用 Context.MODE_PRIVATE 并创建一个 ContentProvider,以便我的应用程序拥有完全控制权将此文件共享给 PDF 阅读器(例如 Adob​​e Reader)。这可能吗?我当前使用如下代码将报告 URI 传递给当前配置的 PDF 阅读器。

    // Fire up a PDF viewer intent for the URL.
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(uri, "application/pdf");
    startActivity(intent);

通过 ContentProvider 类型 URI 是否可以实现同样的效果? content://package/fileid 类型 URI?明天我会尝试一点点,看看是否可以,但如果有人知道只允许 file:// URI,那将会非常有帮助。


更新

我能够通过实现 ContentProvider 子类并覆盖以下方法来令人满意地解决我的问题:

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException 
{
    // The filename is the path in the URI without the initial slash.
    String fileName = uri.getPath().substring(1);
    File file = getContext().getFileStreamPath(fileName);
    return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}

然后,当我触发查看意图时,它会被重写如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.withAppendedPath(Uri.parse("content://providername/"),filePath);
intent.setData(uri);
startActivity(intent);

在我的例子中,我使用 Adob​​e Reader,它可以正确实现从 content:// URI 的加载。

I have some requirements to protect some sensitive data. The data is downloaded as a PDF from a URL and saved as an Application Private file using the following code:

public File downloadPDF(final Context fileContext, Uri reportUri, final String fileName)
{
    try
    {
        HttpGet get = new HttpGet(reportUri.toString());

        File file = httpClient.execute(get, new ResponseHandler<File>()
        {
            @Override
            public File handleResponse(HttpResponse response) throws ClientProtocolException, IOException
            {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
                {
                    response.getEntity().writeTo(fileContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE));
                    return fileContext.getFileStreamPath(fileName);
                }
                return null;
            }
        });

        return file;
    }
    catch (IOException e)
    {
        Log.e(TAG, "Unable to download report.", e);
    }

    return null;
}

Now, what I'd like to do is change this to using Context.MODE_PRIVATE and create a ContentProvider so that my application has complete control over the sharing of this file to a PDF reader such as Adobe Reader. Is this possible? I currently use code like the following to pass the report URI to the currently configured PDF reader.

    // Fire up a PDF viewer intent for the URL.
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(uri, "application/pdf");
    startActivity(intent);

Would the same work through a ContentProvider type URI? A content://package/fileid type URI? I'll be trying a little spike tomorrow to see if I can, but if anyone knows that only file:// URIs are allowed, it would be really helpful.


UPDATE

I was able to solve my problem satisfactorily by implementing a ContentProvider subclass with the following method overridden:

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException 
{
    // The filename is the path in the URI without the initial slash.
    String fileName = uri.getPath().substring(1);
    File file = getContext().getFileStreamPath(fileName);
    return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}

Then, when I fire off the viewing intent, it is rewritten something like the following:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.withAppendedPath(Uri.parse("content://providername/"),filePath);
intent.setData(uri);
startActivity(intent);

And in my case, I use Adobe Reader, which properly implements the loading from content:// URIs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜空下最亮的亮点 2024-10-22 17:13:59

通过 ContentProvider 类型 URI 是否可以实现同样的效果? content://package/fileid 类型 URI?

它应该。您需要让您的ContentProvidergetType()返回application/pdf。而且,某些 PDF 阅读器可能无法处理 content:// Uri 值。

您可以做的是创建 ContentProvider,然后使用 PackageManager 看看是否有任何东西能够理解您的 ACTION_VIEW Intent content:// Uri。如果有回应,你就准备好了。如果没有,您可以回退到使文件可供所有人读取并使用您当前的实现。或者,由于将文件更改为世界可读可能会很痛苦,因此您可以尽早(例如,当您的应用程序启动时)使用 ContentProvider 的一些废 Uri 运行测试> 支持,这样您下载时就知道该走哪条路线。

Would the same work through a ContentProvider type URI? A content://package/fileid type URI?

It should. You will need to have your ContentProvider return application/pdf for getType(). And, it is possible that some PDF readers won't handle content:// Uri values.

What you can do is make the ContentProvider, then use PackageManager to see if anything will understand your ACTION_VIEW Intent on the content:// Uri. If something responds, you're set. If not, you can fall back to making the file be world-readable and using your current implementation. Or, since changing the file to world-readable may be a pain, you could run the test early on (e.g., when your app starts) with some scrap Uri that your ContentProvider supports, so you will know which route to take when you do your downloads.

落日海湾 2024-10-22 17:13:59

没有内容提供商不保护文件

事实上,应用程序可能对来自内容提供商的文件执行的第一件事就是在其缓存目录中创建临时副本。我认为你应该重新审视一下这个问题。

No content providers do not protect files

In fact probably the first thing an app might do with a file from a content provider is make a temporary copy in its cache dir. I think you should revisit this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文