如何获取DownloadManager系统通知中取消按钮的监听器?
解决DownloadManager系统通知取消按钮监听问题
你当前通过轮询DownloadManager状态的方式无法捕获取消事件,核心问题有两个:
- 轮询逻辑未处理取消任务对应的状态码
- 轮询本身是低效且不及时的实现方式
问题分析
当用户点击系统通知的取消按钮时,DownloadManager的任务状态会变为STATUS_FAILED,对应的错误码是ERROR_CANCELED。你当前的代码在STATUS_FAILED分支没有做任何判断,自然无法捕获这个事件。另外,无延迟的轮询会持续占用CPU资源,不是最优方案。
正确实现方式:使用广播接收器
系统在DownloadManager任务完成、失败或取消时,会发送DownloadManager.ACTION_DOWNLOAD_COMPLETE广播,通过监听这个广播可以高效获取任务状态变化:
- 注册动态广播接收器
private val downloadReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val downloadId = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) ?: return // 只处理当前关注的任务 if (downloadId != mDownloadId) return val cursor = downloadManager?.query(DownloadManager.Query().setFilterById(downloadId)) cursor?.let { if (it.moveToFirst()) { val status = it.getInt(it.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)) val reason = it.getInt(it.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON)) when (status) { DownloadManager.STATUS_SUCCESSFUL -> { // 处理下载完成逻辑 progress = 100 } DownloadManager.STATUS_FAILED -> { if (reason == DownloadManager.ERROR_CANCELED) { // 捕获到用户取消下载的事件 // 这里添加你的处理逻辑,比如更新UI、清理数据等 } else { // 处理其他失败情况 } } } } it.close() } } } // 在合适的地方(比如Activity的onCreate)注册广播 registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) // 记得在销毁时注销广播,比如Activity的onDestroy override fun onDestroy() { super.onDestroy() unregisterReceiver(downloadReceiver) }
- 移除低效的轮询代码
你之前的轮询线程可以完全替换为上述广播逻辑,既高效又能准确捕获取消事件。
补充:修复原有轮询代码(不推荐)
如果一定要保留轮询方式,需要在STATUS_FAILED分支判断错误码:
DownloadManager.STATUS_FAILED -> { val reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON) ?: 0) if (reason == DownloadManager.ERROR_CANCELED) { // 用户取消了下载,处理逻辑 complete = false } }
同时要给循环添加延迟(比如Thread.sleep(1000)),避免CPU空转。
内容的提问来源于stack exchange,提问作者Bhoomika Prajapati
相关产品推荐
相关产品推荐

