使用DownloadManager开始下载后是否有可能取消/停止下载?

22

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

有两种可能性: a.用户可以手动取消它,例如通过通知栏中的点击。 b.通过代码取消和删除下载。

我定义了以下接收器。

<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
我会实现自己的下载流程,因为内置的下载管理器有 bug,在旧设备上无法正常工作。 - vortexwolf
@CommonsWare:当通知栏被点击时,我正在调用remove。我假设无论下载是否完成,通知点击事件都会传递。 - PravinCG
我不太清楚。我还没有深入研究过通知点击方面的内容。你可以尝试在一些更容易控制的元素上,比如按钮或操作栏项目中进行remove()实验。此外,你确认downloadId返回了一个值,并且与你最初的请求匹配吗? - CommonsWare
我解决了。对于我来说,我正在下载多个文件,它们会被捆绑在同一个进度条上。因此,现在一旦我收到通知点击广播,我会查询并迭代ID,并逐个删除它们。有效。唯一的问题是我不确定它是否也会删除未由我的应用程序启动的下载。 - PravinCG
2个回答

58
你可以通过调用DownloadManagerremove(long...) 方法来取消下载。为此,您需要下载的ID。根据我的经验,有两种可靠的方法可以获得它:
  1. 记住enqueue(DownloadManager.Request)方法的返回值。
  2. 通过query(DownloadManager.Query)方法查询下载管理器中的下载。然后从返回的Cursor中检索ID,它们存储在名为DownloadManager.COLUMN_ID的列中。

广播接收器

根据我的经验,通过BroadcastReceiver检索下载ID对于android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED操作不可靠(尽管广播总是发送的)。
  1. 从额外的DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS中获取下载ID不能正常工作。在某些设备上,它总是返回null。如果在某些设备上返回了某些内容,则是最先启动的下载的ID。如果第一个下载已完成/取消,则对于其余下载的通知返回null。
  2. 从额外的DownloadManager.EXTRA_DOWNLOAD_ID获取值对于此操作不起作用。
通过android.intent.action.DOWNLOAD_COMPLETE操作获取广播中的ID似乎是可靠的。您必须从额外的DownloadManager.EXTRA_DOWNLOAD_ID获取它。请注意,广播不仅在完成下载时发送,也在调用remove()取消下载时发送。 注意: 有时会将多个下载分组在一个通知中,有时会创建多个通知。我无法弄清楚通知何时会分组或不分组的条件。它似乎取决于许多因素,如操作系统版本、设备、下载标题等,并且总体上似乎相当不可预测。我已经测试过,你不能取消其他应用程序的下载。尽管ID是数据库ID,可在所有应用程序中唯一。调用remove()不会取消其他应用程序的下载。


1
谢谢Tomik,你总结得很好,我同意我也观察到了同样的情况。我接受这个答案,因为它将有助于未来的其他人。 - PravinCG
非常有用。提供个人经验总是最有价值的事情之一,可以节省很多时间。 - mmlooloo
3
@Tomik,那么获取DOWNLOAD_NOTIFICATION_CLICKED上的ID的最佳方法是什么?我正在同时下载多个文件,无法保持所有ID。 - MadDeveloper
如果我不知道ID,因为它是由另一个应用程序或实例启动的怎么办?如何停止所有下载? - djdance
你的答案是正确的。但是要如何重新开始下载呢?你有没有完整的源代码示例? - Md Tariqul Islam

1
如果您想知道如何停止下载,那么我相信您知道如何通过URL下载数据。我希望您熟悉第1点、第2点和第3点,并且您的解决方案是第4点。
1. private var mgr: DownloadManager? = null 2. private var enqueue: Long? = null 3. enqueue = mgr?.enqueue(request) 4. mgr?.remove(enqueue!!)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接