是否可以取消/停止使用 DownloadManager 开始的下载?

Posted

技术标签:

【中文标题】是否可以取消/停止使用 DownloadManager 开始的下载?【英文标题】:Is it possible to cancel/stop a download started using DownloadManager? 【发布时间】:2012-12-13 22:39:15 【问题描述】:

我正在使用 DownloadManager 在我的应用程序中下载一堆文件。我无法弄清楚如何取消已由 downloadManager 排队的下载。

有两种可能: 一种。用户可以通过在通知栏中单击它来手动取消它。 湾。通过代码取消并删除下载。

我定义了以下接收器。

<receiver 
        android:name=".DownloadStatusReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
     </intent-filter>
 </receiver> 

在接收器中

if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) 

    Constants.showLog(TAG, "Notification clicked");
    long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
    DownloadManager dm =(DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);             
    dm.remove(downloadId);


有什么见解吗?

【问题讨论】:

根据文档, remove() 应该可以工作。当然,在下载完成之前,您似乎不会调用remove()。这就像在马跑了之后锁住了谷仓。 :-) 我会实现自己的下载工作流程,因为内置的下载管理器有问题,不能在旧设备上运行。 @CommonsWare:单击通知栏时我正在调用删除。我假设通知点击事件来自下载是否完成。 击败我。我没有玩太多的通知点击。尝试在您的控制范围内尝试使用remove(),例如Button 或操作栏项目。另外,您是否确认 downloadId 会返回一个与您的原始请求相匹配的值? 我修好了。对我来说,我正在下载多个文件,它们在同一个进度条上聚集在一起。所以现在只要我收到点击广播的通知,我就会查询并遍历 Id 并将它们一一删除。作品。我不确定的唯一问题是它是否还会删除我的应用程序未启动的下载。 【参考方案1】:

您可以通过DownloadManager 调用其remove(long...) 方法来取消下载。为此,您需要下载的 ID。根据我的经验,基本上有两种可靠的方法来获得它:

    记住enqueue(DownloadManager.Request)方法的返回值。 通过query(DownloadManager.Query) 方法查询DownloadManager 以获取下载。然后从返回的Cursor中检索ID,它们存储在名为DownloadManager.COLUMN_ID的列中。

广播接收器

根据我的经验,通过 BroadcastReceiver 检索下载 ID 以执行操作 android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED 是不可靠的(尽管总是发送广播)。

    从额外的DownloadManager. EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS 获取下载 ID 无法正常工作。在某些设备上,它总是返回 null。如果它在某些设备上返回某些内容,则它是首先开始下载的 ID。如果第一次下载完成/取消,则返回 null 以通知剩余下载。 从额外的DownloadManager.EXTRA_DOWNLOAD_ID 获取值不适用于此操作。

在广播中获取 ID 以供行动android.intent.action.DOWNLOAD_COMPLETE 似乎可靠。您必须从额外的DownloadManager.EXTRA_DOWNLOAD_ID 获得它。请注意,广播不仅会在下载完成时发送,还会在您取消下载调用remove()时发送。

注意: 下载有时会在一个通知中分组,有时会创建多个通知。我无法弄清楚通知何时分组和不分组的条件。它似乎取决于许多因素,例如操作系统版本、设备、下载标题……而且总体而言似乎相当不可预测。

注意: 我测试了你是否可以取消其他应用程序的下载,但似乎不能。即使 ID 是在所有应用程序中唯一的数据库 ID。调用 remove() 不会取消其他应用的下载。

【讨论】:

感谢 Tomik,您总结得很好,我同意我也观察到了同样的情况。我接受这个答案,因为它会在未来帮助其他人。 非常有用。提供个人经验总是最有价值的东西,你可以节省很多时间。 @Tomik,那么实际上在 DOWNLOAD_NOTIFICATION_CLICKED 上获取 id 的最佳方式是什么?我正在同时下载多个文件,无法保留所有 id。 如果我不知道 ID 怎么办,因为它是由另一个应用程序或实例启动的?如何添加所有下载? 你的答案是正确的。但是如何重新开始下载。你有任何完整的来源作为例子。【参考方案2】:

如果您正在寻找如何停止下载,那么我相信您知道如何通过 URL 下载数据。 我希望您熟悉第 1 点、第 2 点和第 3 点,您的解决方案是第 4 点。

    private var mgr: DownloadManager? = null private var enqueue: Long? = null enqueue = mgr?.enqueue(request) mgr?.remove(enqueue!!)

【讨论】:

以上是关于是否可以取消/停止使用 DownloadManager 开始的下载?的主要内容,如果未能解决你的问题,请参考以下文章

如何立即终止/停止长 SQL 查询?

使用任务取消令牌停止 TCP 侦听器

正确中止或取消 PostAsync

平滑动画停止

有没有办法识别已取消的查询?

在后台播放哔声