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

Android 11以下版本DownloadManager提示下载失败的解决方法

Android 11以下DownloadManager提示download unsuccessful排查与解决

核心排查方向

  • 存储权限缺失:Android 11(API 30)及以上版本,应用通过DownloadManager向Download等公共目录写入文件时,不需要申请存储权限;但API 29及以下版本必须持有WRITE_EXTERNAL_STORAGE权限才能写入外部公共目录,无权限直接提交下载任务会触发失败,这是该问题最高发的原因。
  • MIME类型不匹配:低版本DownloadManager对MIME类型校验逻辑更严格,如果getMimeType(docName)返回的类型和服务端实际返回的文件Content-Type不一致,会直接判定下载失败;Android 12对该场景做了容错,不会直接中断任务。
  • 文件名非法:低版本系统不会自动转义文件名中的非法字符,如果传入的fileName包含/、\、:、*、?、"、<、>、|这类文件系统不支持的字符,会因为无法创建目标文件导致下载失败,高版本系统会自动替换非法字符完成文件创建。
  • 网络规则兼容问题:如果下载链接是HTTP明文地址、或者使用了低版本系统信任库未收录的HTTPS证书,低版本DownloadManager会直接拦截网络请求,高版本系统可能因为证书库更新、网络规则兼容度更高可以正常下载。

可落地解决方案

  1. 补全权限适配
    在清单文件中声明对应权限,注意按系统版本做权限范围限制:
    <!-- Android 9及以下版本需要写外部存储权限才能通过DownloadManager写入公共下载目录 -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
    
    在Android 9及以下设备上,先动态申请WRITE_EXTERNAL_STORAGE权限,用户授权后再调用dm.enqueue(request)提交下载任务。
  2. 修正MIME类型设置逻辑
    如果无法100%确定文件的准确MIME类型,直接删除request.setMimeType(getMimeType(docName))这行代码,让DownloadManager自动根据服务端返回的Content-Type头识别文件类型;如果必须本地设置MIME,匹配失败时兜底传通用类型*/*,避免校验不通过。
  3. 提前校验文件名合法性
    传入目标文件名前,替换所有非法字符,避免文件创建失败:
    // 替换文件系统不支持的特殊字符为下划线
    fileName = fileName.replaceAll("[/\\\\:*?\"<>|]", "_");
    
  4. 兼容网络规则
    • 如果存在HTTP明文下载链接,在清单文件的<application>标签下添加android:usesCleartextTraffic="true",允许明文传输。
    • 如果使用自签名/私有CA签发的HTTPS证书,通过网络安全配置将对应根证书预埋到应用中,兼容低版本系统证书库不全的问题。

失败原因定位方法

提交下载任务后会返回唯一的downloadId,下载失败时可以通过查询DownloadManager拿到具体错误码,精准定位问题:

long downloadId = dm.enqueue(request);
// 下载失败时触发查询
Cursor cursor = dm.query(new DownloadManager.Query().setFilterById(downloadId));
if (cursor != null && cursor.moveToFirst()) {
    int status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
    if (status == DownloadManager.STATUS_FAILED) {
        int errorCode = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON));
        // 对照errorCode可定位具体原因:比如1004是HTTP错误、1008是证书错误、1007是文件创建失败
    }
    cursor.close();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:57:27