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

如何获取DownloadManager系统通知中取消按钮的监听器?

解决DownloadManager系统通知取消按钮监听问题

你当前通过轮询DownloadManager状态的方式无法捕获取消事件,核心问题有两个:

  • 轮询逻辑未处理取消任务对应的状态码
  • 轮询本身是低效且不及时的实现方式

问题分析

当用户点击系统通知的取消按钮时,DownloadManager的任务状态会变为STATUS_FAILED,对应的错误码是ERROR_CANCELED。你当前的代码在STATUS_FAILED分支没有做任何判断,自然无法捕获这个事件。另外,无延迟的轮询会持续占用CPU资源,不是最优方案。

正确实现方式:使用广播接收器

系统在DownloadManager任务完成、失败或取消时,会发送DownloadManager.ACTION_DOWNLOAD_COMPLETE广播,通过监听这个广播可以高效获取任务状态变化:

  1. 注册动态广播接收器
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)
}
  1. 移除低效的轮询代码
    你之前的轮询线程可以完全替换为上述广播逻辑,既高效又能准确捕获取消事件。

补充:修复原有轮询代码(不推荐)

如果一定要保留轮询方式,需要在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:10:32