Android:intentservice,如何中止或跳过handleintent队列中的任务

Posted

技术标签:

【中文标题】Android:intentservice,如何中止或跳过handleintent队列中的任务【英文标题】:Android: intentservice, how abort or skip a task in the handleintent queue 【发布时间】:2011-11-11 05:33:24 【问题描述】:

我有一个调用意图服务(“DownloadService”)的活动(“ApplicationActivity”)

intentService 在后台从互联网下载文件,但我希望能够中止特定的下载............

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

intent 服务开始下载数字 1,然后是第二个,依此类推.... 1)有没有办法在方法句柄事件中告诉意图服务中止你正在做的事情(在这种情况下是下载文件1)并开始下载下一个?

2)是否可以从队列中删除元素,例如在下载文件1时,从队列中删除文件4,以便在数字3之后直接进入5?

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

Tnx

【问题讨论】:

即使现在我也想要同样的东西,你的问题解决了吗? 【参考方案1】:

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

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

首先我将here的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);

像魅力一样工作:)

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

【讨论】:

干得好。它是否也停止正在运行的操作或只是停止排队的操作? 我认为它不会停止运行操作。没有什么比测试更重要的了。也许通过对原始 IntentService 源进行更多修改,您可以实现这一点。 您应该在消息中明确分配 what 字段,而不是假设它的值为 0。what 未在源中使用,因此将其用于您自己的目的应该是安全的. 链接更新:IntentService 的来源现在位于android.googlesource.com/platform/frameworks/base【参考方案2】:

我创建自己的 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

【讨论】:

【参考方案3】:

扩展 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);
        
    

我知道此代码有效,因为我之前对其进行了测试,但我不确定这是一种正确的方法!

【讨论】:

这不会停止已经运行的服务。除此之外,这是一个很好且简单的解决方案。【参考方案4】:

您可以绑定到意图服务并创建一个方法来取消或取消下载。

Here 是您可能需要的快速教程

【讨论】:

我快速阅读了教程,但我不明白它在我的情况下如何有用.....它是用于服务而不是意图服务......另一个目的........我的问题是意图服务类不提供任何与队列拨号的方法......我唯一能想到的就是复制和粘贴意图服务类并修改它...... . 嗨。 intentservice 它是服务的基类。您仍然可以对其进行绑定。绑定用于与服务交互。因此,在 bind 中,您可以使用 stopcurrent 甚至 dequeu 方法来设置一些标志,或者如果您有队列对象,则使文件出队。【参考方案5】:

正如上面@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)一样清除队列。

希望对您有所帮助。

【讨论】:

以上是关于Android:intentservice,如何中止或跳过handleintent队列中的任务的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何确定 IntentService 是不是正在运行?

转载Android IntentService使用全面介绍及源码解析

Android Service为IntentService扩展ResultReceiver,CREATOR如何实现?

在Android O中运行后台运行Intentservice

如何在 Android 中服务 onDestroy 后保持对象变量处于活动状态?

android 中IntentService的使用场景