首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓DownloadManager和FileProvider

安卓DownloadManager和FileProvider
EN

Stack Overflow用户
提问于 2018-07-01 00:44:48
回答 2查看 5.6K关注 0票数 1

我想使用Android的DownloadManager下载一个pdf,然后让用户使用他的pdf阅读器应用程序打开它。

为了做到这一点,我使用以下命令来节省启动下载的时间:

代码语言:javascript
复制
public String downloadFile(String url, String name) {
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setDescription("Downloading file: " + name);
        request.setTitle("My app name");
        request.allowScanningByMediaScanner();
     request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setMimeType("application/pdf");
        Uri destinationUri = Uri.fromFile(new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name+".pdf"));
        request.setDestinationUri(destinationUri);
        manager.enqueue(request);
        return destinationUri.toString();
    }

我正在保存Uri,并使用它通过PDF视图应用打开PDF,如下所示:

代码语言:javascript
复制
public void openDownloadedFile(String uri) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    File file = new File(uri);
    Uri uriForFile = FileProvider.getUriForFile(context.getApplicationContext(), context.getString(R.string.my_file_authority), file);
    intent.setDataAndType(uriForFile, "application/pdf");
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    context.startActivity(intent);
}

My application的清单文件包含以下提供程序:

代码语言:javascript
复制
        <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="@string/my_file_authority"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>

并且我在provider_paths中还有以下内容

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path
        name="my_pdfs"
        path="."/>
    <external-path
        name="my_pdfs"
        path="."/>
    <files-path
        name="my_pdfs"
        path="."/>
</paths>

我知道有两个额外的元素,但我只是想确保我不会遗漏一些东西。

不幸的是,这会崩溃,原因如下:

代码语言:javascript
复制
java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/Android/data/{my_app_id}/files/Download/filename_of_pdf.pdf
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:738)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:417)

一些其他详细信息:

代码语言:javascript
复制
minSdkVersion 21
targetSdkVersion 27

我正在三星S8和安卓模拟器上测试安卓O。

有没有人能告诉我为什么会这样?我怎么知道安卓正在考虑我的provider_paths?

谢谢!

PS:

  • 我试图为DownloadManager使用外部公共目录,但它崩溃了,并说它没有权限,即使在我的清单中我确实有WRITE_EXTERNAL_STORAGE权限,并且我请求用户权限,但对话框没有出现。
  • 我也替换了“”。在下载文件中使用"Download“或"Android”,甚至“Android/ provider_paths.xml /{my_app_id}/files/Download/”,但我得到了相同的crash
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-01 01:23:00

代码语言:javascript
复制
File file = new File(uri);

Uri不是文件。

代码语言:javascript
复制
java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/Android/data/{my_app_id}/files/Download/filename_of_pdf.pdf

/file:/storage/emulated/0/Android/data/{my_app_id}/files/Download/filename_of_pdf.pdf不是Android上的文件系统路径(对于任何其他操作系统,都不是)。

要解决此问题,请执行以下操作:

使用getUriForFile()

  1. new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name+".pdf")结果保存为destinationUri实例化的File
票数 1
EN

Stack Overflow用户

发布于 2019-07-27 21:05:59

我来这里有点晚了,但看到我也在为此而苦苦挣扎,我想我应该提供我最终找到的解决方案:经过大量的挖掘,我发现我们必须小心使用file://content://。这两种方法都用作Uris,但第一种方法是公开访问文件(DownloadManager方法),另一种是通过权限访问(FileProvider方法)。

我将总结一下我是如何做到这一点的。在我的例子中,我在应用程序中使用下载的文件(从mp3提取元数据,然后播放它)。我已经包含了检索我所使用的文件的方法,就像这里一样,它也是许多试验性错误,以确定使用哪种方法来访问文件。因此,希望我能帮助那些也在尝试浏览Uris和权限迷宫的其他人。

使用DownloadManager下载文件

代码语言:javascript
复制
 //set up the download manager and the file destination
 final DownloadManager dlManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
 String destination = Environment.getExternalStorageDirectory() + "*APPFOLDER*";

 //ensure the folder exists before continuing
 File file = new File(destination);
 if (!file.exists())
 file.mkdirs();

 destination += "/" + "*FILENAME*";
 final Uri destinationUri = Uri.parse("file://" + destination);

 //create the download request
 DownloadManager.Request dlRequest = new DownloadManager.Request(uri);
 dlRequest.setDestinationUri(destinationUri);
 final long dlId = dlManager.enqueue(dlRequest);

访问文件的

代码语言:javascript
复制
File myPath = new File(Environment.getExternalStorageDirectory(), "*APPFOLDER*");
File myFile = new File(myPath, "*FILENAME*");
Uri myUri = FileProvider.getUriForFile(ctxt, ctxt.getApplicationContext().getPackageName() + ".file_provider", myFile);
ctxt.grantUriPermission(ctxt.getApplicationContext().getPackageName(), myUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
    mmr.setDataSource(ctxt, myUri);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51116743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档