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

使用Download Manager实现下载完成通知的最佳方案是什么?

Android DownloadManager 下载完成监听实现方案

实现思路

系统DownloadManager在任务完成时会发送全局广播DownloadManager.ACTION_DOWNLOAD_COMPLETE,我们只需要注册对应广播接收器,匹配本次下载任务的唯一ID,校验下载状态后即可弹出对应提示。

完整实现步骤

  • 第一步:存储下载任务唯一ID
    先在Activity/Fragment类中声明变量存储下载任务ID,多个下载任务可改用List<Long>存储:
private var currentDownloadId: Long = -1

修改原有downloadManager方法,接收enqueue方法返回的任务ID:

private fun downloadManager(url: String?) {
    if (URLUtil.isValidUrl(url)) {
        val request = DownloadManager.Request(Uri.parse(url)).apply {
            allowScanningByMediaScanner()
            setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            setDestinationInExternalPublicDir(
                Environment.DIRECTORY_DOWNLOADS,
                URLUtil.guessFileName(url, null, null)
            )
        }
        val downloadManager = ContextCompat.getSystemService(this, DownloadManager::class.java)!!
        // 保存返回的唯一任务ID
        currentDownloadId = downloadManager.enqueue(request)
    }
}
  • 第二步:创建下载完成广播接收器
    在类中声明广播接收器实例,处理下载完成的逻辑:
private val downloadReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        // 校验广播类型
        if (intent?.action != DownloadManager.ACTION_DOWNLOAD_COMPLETE) return
        // 获取已完成的任务ID
        val completeId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
        // 匹配是否为当前应用发起的下载任务
        if (completeId != currentDownloadId) return

        // 查询下载最终状态
        val query = DownloadManager.Query().setFilterById(currentDownloadId)
        val downloadManager = ContextCompat.getSystemService(context!!, DownloadManager::class.java)!!
        val cursor = downloadManager.query(query)
        if (cursor.moveToFirst()) {
            val status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
            when (status) {
                DownloadManager.STATUS_SUCCESSFUL -> {
                    Toast.makeText(context, "下载完成", Toast.LENGTH_SHORT).show()
                    // 替换为Snackbar示例:Snackbar.make(window.decorView, "下载完成", Snackbar.LENGTH_SHORT).show()
                }
                DownloadManager.STATUS_FAILED -> {
                    val errorCode = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON))
                    Toast.makeText(context, "下载失败,错误码:$errorCode", Toast.LENGTH_SHORT).show()
                }
            }
        }
        cursor.close()
    }
}
  • 第三步:注册/注销广播接收器
    在对应生命周期方法中完成广播的注册和注销,避免内存泄漏:
override fun onStart() {
    super.onStart()
    // 注册广播,仅接收下载完成的广播事件
    val filter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
    registerReceiver(downloadReceiver, filter)
}

override fun onStop() {
    super.onStop()
    // 页面不可见时注销广播
    unregisterReceiver(downloadReceiver)
}

多任务适配说明

如果同时发起多个下载任务,只需要将currentDownloadId替换为MutableList<Long>存储所有任务ID,收到广播时遍历列表匹配对应ID即可。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:27:04