安卓:IntentService,如何中止或跳过handleintent队列中的任务

16

我有一个活动("ApplicationActivity"),它调用了意图服务("DownloadService")。

该意图服务会在后台从互联网下载文件,但我想要能够中止特定的下载......

假设我将5个文件放入队列:文件1、2、3、4、5。

意图服务开始下载第1个,然后是第2个,等等... 1) 有没有办法告诉意图服务在事件处理方法(在这种情况下是下载文件1)中中止正在进行的操作并开始下载下一个呢?

2) 是否可以从队列中删除元素,例如在下载文件1时,将文件4从队列中删除,以便在完成3之后直接跳到5?

简而言之,我需要一种与队列通信的方法来执行这两个简单的操作,但我在互联网上没有找到任何有用的信息:(

谢谢


现在我还想要同样的东西,你的问题解决了吗? - Pandiri Deepak
5个回答

19

感谢 @user280560,根据您的评论我找到了解决方案 :)

只是为了举一个更具体的例子,在某些情况下我想清除队列。

首先,我从这里复制了 IntentService.java 的源代码到我的项目中(不需要更改名称,您可以保留 IntentService.java,只是导入您的文件而不是 Android 的)。 然后我添加了这个

public void clearQueue() {
    Debug.PrintInfo(TAG, "All requests removed from queue");
    mServiceHandler.removeMessages(0);
}

我希望你能翻译我的IntentService源代码。

现在,我的服务继承了IntentService,当特定的操作(如登录)传递到服务时,我想从我的服务中清除队列,所以我重写了onStartMethod方法,例如:

@Override
public void onStart(Intent intent, int startId) {
    if(intent.getAction().equals(ACTION_LOGIN)) {
        //Login clears messages in the queue
        clearQueue();
    }
    super.onStart(intent, startId);
}

非常好用 :)

希望能对某些人有所帮助...


1
干得好。它会停止正在运行的操作还是只停止排队的操作? - Martin Vandzura
我不认为它停止运行操作。不过,测试一下就知道了。也许通过进一步修改原始的IntentService源代码,你可以实现这个功能。 - Joao Sousa
5
你应该明确地为消息指定 what 字段,而不是假设它的值为0。在源代码中没有使用 what,因此在你自己的目的中使用它应该是安全的。 - Jeffrey Blattman
1
链接更新:IntentService的源代码现在位于https://android.googlesource.com/platform/frameworks/base。 - deepwinter

12

我创建了自己的MyIntentService类,复制了原始代码并修改了其中的方法,以满足我的需求......特别是为了出列一个元素,你可以在我的情况下使用ServiceHandler的方法:
mServiceHandler.removeMessages(appId);
这将删除消息队列中任何带有特定代码“what”的待处理消息,这意味着您必须在每个消息的“what”字段中添加标识符来标记您添加到队列中的每个消息。例如

public void onStart(Intent intent, int startId) 
{
    super.onStart(intent, startId);
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    msg.what = intent.getIntExtra("appId", 0); \\parameters that come from the outside

5

扩展IntentService类并声明一个取消项目的列表,每当您想要取消某个项目时,将其添加到此列表中。最后,在处理您的意图之前,请确保它尚未被取消!

public class MyDownloadService extends IntentService {
    private static List<String> canceledUrl;

    public static void cancelDownload(String url){
         canceledUrl.add(url);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String url = intent.getStringExtra(EXTRA_URL);

            if(!canceledUrl.contains(url)) //if download has not been canceled already
                downloadFile(url);
            else
                canceledUrl.remove(url);
        }
    }
}

我知道这段代码能够工作,因为之前我已经测试过了,但我不确定这是否是正确的做法!


这不会停止已经运行的服务。除此之外,这是一个好的和简单的解决方案。 - diyoda_

1

您可以绑定到IntentService并创建一个方法来取消或取消下载队列。

这里是一个快速教程,可能会对您有所帮助


我快速阅读了教程,但是我不明白它如何在我的情况下有用......它是为服务而不是意图服务设计的.......并且是为了另一个目的而设计的.......我的问题是意图服务类没有提供任何处理队列的方法......我唯一能想到的就是复制和粘贴IntentService类并进行修改.... - Sgotenks
嗨。IntentService是服务的基类。您仍然可以将其绑定。绑定用于与服务交互。因此,在绑定中,您可以有一个stopcurrent甚至dequeu方法,该方法设置一些标志或从队列对象中出队文件。 - Pintac

0

正如@JeffreyBlattman所说,最好安全起见,将自己的“what”值分配给消息,就像这样

@Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        msg.what = 0;
        mServiceHandler.sendMessage(msg);
    }

并清空队列,例如mServiceHandler.removeMessages(0)

希望这有所帮助。


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