Android下载管理器代码旧设备正常,最新版本设备失效问题求助
Android 8+设备下载功能失效的修复方案
1. 解决明文HTTP拦截问题(Android 9及以上)
Android 9开始默认禁止明文HTTP流量,你的下载链接是http://开头,会被系统拦截。可通过以下两种方式解决:
- 推荐方案:将链接替换为HTTPS协议,把
http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4改为https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4 - 允许指定域名明文流量:在
res/xml目录创建network_security_config.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">commondatastorage.googleapis.com</domain> </domain-config> </network-security-config>
然后在AndroidManifest.xml的<application>标签中添加配置:
android:networkSecurityConfig="@xml/network_security_config"
2. 适配Android 13+的通知权限
Android 13新增POST_NOTIFICATIONS权限,DownloadManager需要该权限才能推送下载通知,否则可能静默失败:
- 在
AndroidManifest.xml中声明权限:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
- 动态申请权限(targetSdk>=33时):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> // 处理权限申请结果 } requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) }
3. 优化代码健壮性
- 移除强制非空断言
!!,避免空指针异常:
val dm = getSystemService(DOWNLOAD_SERVICE) as? DownloadManager dm?.let { downloadManager -> val url = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4" val request = DownloadManager.Request(Uri.parse(url)) val fileName = url.substring(url.lastIndexOf('/') + 1).let { it.substring(0, 1).uppercase(Locale.getDefault()) + it.substring(1) } request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, fileName) // 可选:添加通知标题和描述,提升用户体验 request.setTitle("视频下载") request.setDescription("正在下载ElephantsDream.mp4") enqueue = downloadManager.enqueue(request) }
4. 监听下载状态排查问题
添加广播接收器获取下载结果,方便定位失败原因:
private val downloadReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val downloadId = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) ?: -1 if (downloadId == enqueue) { dm?.query(DownloadManager.Query().setFilterById(downloadId))?.use { cursor -> if (cursor.moveToFirst()) { val status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)) when (status) { DownloadManager.STATUS_SUCCESSFUL -> { // 处理下载成功逻辑 } DownloadManager.STATUS_FAILED -> { val errorReason = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON)) // 根据errorReason排查具体失败原因,比如ERROR_FILE_ERROR、ERROR_UNHANDLED_HTTP_CODE等 } } } } } } } // 在Activity onCreate中注册接收器 registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) // 在Activity onDestroy中注销接收器 override fun onDestroy() { super.onDestroy() unregisterReceiver(downloadReceiver) }
内容的提问来源于stack exchange,提问作者Khush Parmar
相关产品推荐
相关产品推荐

