如何为Android Download Manager设置2分钟超时及处理代码中的超时逻辑
Android Download Manager 超时处理与启用/禁用实现
需求说明
需要为Android Download Manager设置2分钟超时,超时后处理下载任务,同时实现超时后启用或禁用Download Manager的相关操作。以下是原有的文件下载Kotlin代码:
fun downloadFile(url: String) { val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val downloadUri = Uri.parse(url) val request = DownloadManager.Request(downloadUri).apply { try { setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(true) .setTitle(url.substring(url.lastIndexOf("/") + 1)) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) .setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS, url.substring(url.lastIndexOf("/") + 1) ) } catch (e: Exception) { e.printStackTrace() } } val downloadId = downloadManager.enqueue(request) val query = DownloadManager.Query().setFilterById(downloadId) }
解决方案
1. 实现2分钟超时监控与任务取消
DownloadManager本身没有内置超时机制,我们可以通过协程定时器或Handler实现超时逻辑,2分钟后检查下载状态,若仍在进行则取消任务:
使用协程实现(适配Kotlin协程生态)
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch // 全局变量控制是否允许发起新下载请求 private var isDownloadAllowed = true fun downloadFile(url: String) { if (!isDownloadAllowed) { // 禁用状态下直接返回,不发起下载 return } val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val downloadUri = Uri.parse(url) val request = DownloadManager.Request(downloadUri).apply { try { setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(true) .setTitle(url.substring(url.lastIndexOf("/") + 1)) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) .setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS, url.substring(url.lastIndexOf("/") + 1) ) } catch (e: Exception) { e.printStackTrace() } } val downloadId = downloadManager.enqueue(request) val query = DownloadManager.Query().setFilterById(downloadId) // 启动2分钟超时定时器 CoroutineScope(Dispatchers.IO).launch { delay(2 * 60 * 1000) // 2分钟延迟 val cursor = downloadManager.query(query) if (cursor.moveToFirst()) { val status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)) if (status == DownloadManager.STATUS_RUNNING) { // 超时仍在下载,取消当前任务 downloadManager.remove(downloadId) // 超时后禁用下载功能(根据需求改为true则是启用) isDownloadAllowed = false } } cursor.close() } }
使用Handler实现(兼容非协程场景)
private var isDownloadAllowed = true private val timeoutHandler = Handler(Looper.getMainLooper()) fun downloadFile(url: String) { if (!isDownloadAllowed) { return } val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager val downloadUri = Uri.parse(url) val request = DownloadManager.Request(downloadUri).apply { try { setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE) .setAllowedOverRoaming(true) .setTitle(url.substring(url.lastIndexOf("/") + 1)) .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) .setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS, url.substring(url.lastIndexOf("/") + 1) ) } catch (e: Exception) { e.printStackTrace() } } val downloadId = downloadManager.enqueue(request) val query = DownloadManager.Query().setFilterById(downloadId) // 2分钟后执行超时检查 timeoutHandler.postDelayed({ val cursor = downloadManager.query(query) if (cursor.moveToFirst()) { val status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)) if (status == DownloadManager.STATUS_RUNNING) { downloadManager.remove(downloadId) // 禁用下载功能 isDownloadAllowed = false } } cursor.close() }, 2 * 60 * 1000) } // 页面销毁时移除Handler回调,避免内存泄漏 override fun onDestroy() { super.onDestroy() timeoutHandler.removeCallbacksAndMessages(null) }
2. 关于启用/禁用DownloadManager的说明
普通应用没有权限直接启用或禁用系统级的DownloadManager服务,上述代码中的isDownloadAllowed变量是通过业务逻辑控制是否允许发起新的下载请求,属于应用内的功能控制。如果需要真正控制系统DownloadManager服务的启停,需要系统级权限(如android.permission.MANAGE_DOWNLOADS),仅适用于系统应用或已root的设备,普通应用无法实现。
内容的提问来源于stack exchange,提问作者Android Dev
相关产品推荐
相关产品推荐

