You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中使用DownloadManager下载文件失败问题求助

解决DownloadManager无法下载file:// URI的问题

这个报错已经说得很直白了:DownloadManager的设计初衷就是用于从网络(HTTP/HTTPS)下载文件,它完全不支持本地file://协议的URI,所以直接传入这类路径必然会抛出IllegalArgumentException

下面根据不同场景给你对应的解决方案:

场景1:文件在你的应用私有存储中

如果这个file://指向的是你自己应用内部存储里的文件,完全没必要用DownloadManager,直接通过文件复制的方式把它移动到公共下载目录或者你需要的位置就行。

示例代码:

private void copyFileToDownloads(File sourceFile) {
    String fileName = sourceFile.getName();
    // Android 10及以上,用MediaStore写入公共下载目录
    ContentValues values = new ContentValues();
    values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
    values.put(MediaStore.Downloads.MIME_TYPE, "application/pdf");
    values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

    ContentResolver resolver = getContentResolver();
    Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);

    if (uri != null) {
        try (OutputStream os = resolver.openOutputStream(uri);
             InputStream is = new FileInputStream(sourceFile)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            Toast.makeText(this, "文件已保存到下载目录", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
            // 这里可以添加异常提示逻辑
        }
    }
}

场景2:文件来自其他应用的共享URI(比如文件选择器返回的路径)

如果这个URI是从其他应用获取的(比如用户通过文件管理器选的文件),先确保你有访问该URI的权限,然后同样通过复制文件的方式处理,而非DownloadManager。如果是content://类型的URI,直接用ContentResolver读取输入流即可:

private void copyContentUriToDownloads(Uri contentUri) {
    String fileName = getFileNameFromContentUri(contentUri);
    if (fileName == null) fileName = "unknown.pdf";

    ContentValues values = new ContentValues();
    values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
    values.put(MediaStore.Downloads.MIME_TYPE, "application/pdf");
    values.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);

    ContentResolver resolver = getContentResolver();
    Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);

    if (uri != null) {
        try (OutputStream os = resolver.openOutputStream(uri);
             InputStream is = resolver.openInputStream(contentUri)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            Toast.makeText(this, "文件已保存", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 辅助方法:从content URI中提取文件名
private String getFileNameFromContentUri(Uri uri) {
    String fileName = null;
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
        if (nameIndex != -1) {
            fileName = cursor.getString(nameIndex);
        }
        cursor.close();
    }
    return fileName;
}

补充说明

再啰嗦一句:DownloadManager是系统提供的网络下载专属工具,它负责后台任务管理、断点续传、通知栏进度展示等功能,但这些都是针对网络资源设计的。本地文件完全不需要这些能力,直接做文件操作反而更高效。

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

火山引擎 最新活动