Android P模拟器中DownloadManager无法启动下载的问题求助
Android P中DownloadManager无法启动下载的问题分析与解决
Hey,这个问题我之前也碰到过,确实是Android P(API 28)的特性变更搞的鬼!
问题根源
Android 9.0开始,系统对跨进程的URI访问做了严格限制——DownloadManager是系统级的后台服务,和你的APP属于不同进程。你之前用Uri.fromFile(file)生成的file://格式URI,在传递给DownloadManager时会被系统拦截,因为这种URI属于"明文文件路径暴露",违反了Android P的安全规范。而Oreo及更早的系统没有这么严格的限制,所以你的代码能正常运行。
两种解决方案,按需选择
方案一:直接用DownloadManager的内置方法(最简便)
因为你要保存文件的路径是APP专属的外部存储目录(getExternalFileStorageDirectory()),DownloadManager本身就有权限直接操作这个目录,完全不用自己生成URI。把代码改成这样就行:
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(URLS.URLforDownloadingFileData(fileName))); // 直接指定存储路径:APP外部专属目录 + 文件名 downloadRequest.setDestinationInExternalFilesDir(getApplicationContext(), null, fileName); downloadRequest.setTitle(titleOfDownload); downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); downloadManager.enqueue(downloadRequest);
这个方法会自动帮你处理路径和权限问题,代码更简洁,也不会触发任何安全限制。
方案二:用FileProvider生成content:// URI(自定义路径时用)
如果你的下载目标路径不是APP专属目录,就需要用FileProvider来生成安全的content:// URI,步骤如下:
- 在AndroidManifest.xml注册FileProvider
在<application>标签内添加:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
(如果用旧版support库,把androidx.core.content.FileProvider换成android.support.v4.content.FileProvider即可)
- 创建路径配置文件
在res/xml目录下新建file_paths.xml(没有xml目录就手动创建):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 对应你的外部存储目录,path="."表示共享该目录下所有文件 --> <external-files-path name="download_files" path="." /> </paths>
- 修改代码生成content URI
把原来的Uri.fromFile(file)替换成FileProvider的方法:
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(URLS.URLforDownloadingFileData(fileName))); File file = new File(mobileInfo.getExternalFileStorageDirectory(),fileName); // 生成安全的content:// URI Uri destinationUri = FileProvider.getUriForFile( getApplicationContext(), getPackageName() + ".fileprovider", // 和Manifest里的authorities必须一致 file ); downloadRequest.setDestinationUri(destinationUri); downloadRequest.setTitle(titleOfDownload); downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); downloadManager.enqueue(downloadRequest);
总结
- 问题本质:Android P禁止跨进程传递
file://URI,导致DownloadManager无法接收你的下载路径。 - 优先选方案一,因为适配成本最低,完全符合Android的安全规范。
内容的提问来源于stack exchange,提问作者Dishonered
相关产品推荐
相关产品推荐

