Android应用下载文件后用Intent打开触发FileProvider异常求助
解决FileProvider无法访问公共Download目录文件的IllegalArgumentException问题
你遇到的这个异常,核心原因是从DownloadManager.COLUMN_LOCAL_URI拿到的字符串是一个完整的Uri(格式是file:///storage/emulated/0/Download/xxx.pdf),而你直接把这个字符串传给new File(filePath),会生成一个路径为/file:/storage/emulated/0/Download/Colors.pdf的错误File对象——这显然不是真实的文件路径,所以FileProvider找不到对应的根目录配置。
下面是具体的修复方案和细节说明:
一、修正文件路径的获取方式
不要直接用COLUMN_LOCAL_URI的字符串创建File,而是先把它解析成Uri,再提取真实路径:
// 替换原来的filePath获取逻辑 String uriString = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); Uri fileUri = Uri.parse(uriString); File file = new File(fileUri.getPath());
如果你的设备API版本低于24,也可以直接用DownloadManager.COLUMN_LOCAL_FILENAME获取绝对路径(这个字段在API24后标记为deprecated,但实际仍可使用):
String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); File file = new File(filePath);
二、确认FileProvider配置正确性
你的provider_paths.xml和Manifest配置是没问题的:
<!-- provider_paths.xml --> <paths> <external-path name="external_files" path="."/> </paths>
<external-path>对应的就是外部存储根目录/storage/emulated/0/,公共Download目录正好在这个根目录下,所以配置完全适配你的场景。
三、完整修复后的BroadcastReceiver代码
BroadcastReceiver downloadReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { long receivedId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (id == receivedId) { Query query = new Query(); query.setFilterById(id); Cursor cursor = manager.query(query); if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); if (DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(columnIndex)) { // 修正路径获取逻辑 String uriString = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); Uri fileUri = Uri.parse(uriString); File file = new File(fileUri.getPath()); // 生成FileProvider的访问Uri Uri contentUri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", file); Intent intent1 = new Intent(Intent.ACTION_VIEW); intent1.setData(contentUri); // 主动指定MIME类型,帮助系统匹配合适的打开应用 intent1.setType("application/pdf"); intent1.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 防止没有可用应用打开文件导致崩溃 if (intent1.resolveActivity(getPackageManager()) != null) { startActivity(intent1); } } } // 务必关闭Cursor,避免内存泄漏 if (cursor != null) cursor.close(); unregisterReceiver(this); } } };
额外注意事项
- 关闭StrictMode只是临时方案:它会掩盖应用潜在的安全和性能问题,不推荐长期使用;
- 指定MIME类型:打开PDF时主动设置
application/pdf,能避免部分应用无法识别文件类型的问题; - 判断可用应用:调用
startActivity前用resolveActivity检查,防止因没有适配的应用导致崩溃。
内容的提问来源于stack exchange,提问作者Un Known
相关产品推荐
相关产品推荐

