You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
        }
    }
};

额外注意事项

  1. 关闭StrictMode只是临时方案:它会掩盖应用潜在的安全和性能问题,不推荐长期使用;
  2. 指定MIME类型:打开PDF时主动设置application/pdf,能避免部分应用无法识别文件类型的问题;
  3. 判断可用应用:调用startActivity前用resolveActivity检查,防止因没有适配的应用导致崩溃。

内容的提问来源于stack exchange,提问作者Un Known

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:30:33