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会直接拦截网络请求,高版本系统可能因为证书库更新、网络规则兼容度更高可以正常下载。
可落地解决方案
- 补全权限适配
在清单文件中声明对应权限,注意按系统版本做权限范围限制:
在Android 9及以下设备上,先动态申请<!-- 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" />WRITE_EXTERNAL_STORAGE权限,用户授权后再调用dm.enqueue(request)提交下载任务。 - 修正MIME类型设置逻辑
如果无法100%确定文件的准确MIME类型,直接删除request.setMimeType(getMimeType(docName))这行代码,让DownloadManager自动根据服务端返回的Content-Type头识别文件类型;如果必须本地设置MIME,匹配失败时兜底传通用类型*/*,避免校验不通过。 - 提前校验文件名合法性
传入目标文件名前,替换所有非法字符,避免文件创建失败:// 替换文件系统不支持的特殊字符为下划线 fileName = fileName.replaceAll("[/\\\\:*?\"<>|]", "_"); - 兼容网络规则
- 如果存在HTTP明文下载链接,在清单文件的
<application>标签下添加android:usesCleartextTraffic="true",允许明文传输。 - 如果使用自签名/私有CA签发的HTTPS证书,通过网络安全配置将对应根证书预埋到应用中,兼容低版本系统证书库不全的问题。
- 如果存在HTTP明文下载链接,在清单文件的
失败原因定位方法
提交下载任务后会返回唯一的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
相关产品推荐
相关产品推荐

