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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:50:36