首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止启动GcmTaskService两次

防止启动GcmTaskService两次
EN

Stack Overflow用户
提问于 2015-06-03 12:02:59
回答 3查看 1.6K关注 0票数 2

我创建了一个非常简单的服务,用于更新服务器上的用户位置:

代码语言:javascript
复制
public class LocationSchedulerService extends GcmTaskService {

    @Override
    public int onRunTask(TaskParams taskParams) {
        // Update to server stuff

        return GcmNetworkManager.RESULT_SUCCESS;
    }
}

我创建了一个简单的BootBroadcastReceiver,以便在设备启动时启动服务:

代码语言:javascript
复制
PeriodicTask task = new PeriodicTask.Builder()
        .setTag("LocationSchedulerService")
        .setService(LocationSchedulerService.class)
        .setPeriod(LOCATION_UPDATE_PERIOD * 60)
        .setFlex(LOCATION_UPDATE_FLEX * 60)
        .setPersisted(false)
        .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED)
        .setRequiresCharging(false)
        .setUpdateCurrent(true)
        .build();

GcmNetworkManager.getInstance(context).schedule(task);

现在我的问题是:

由于不可能知道用户何时安装了包,所以我也希望在用户启动应用程序时启动此任务。但是,如何防止任务运行两次呢?

我读过setUpdateCurrent的文档,但不确定它的功能。这是否意味着当前运行的服务将被取消,或者它正是我想要的?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-06-20 00:06:26

您所描述的就是为什么引入了setUpdateCurrent --应用程序想要一种“只在任务还不存在的情况下才安排任务”的方法。

但是,您所说的“如何防止任务运行两次”是什么意思呢?您正在调度一个PeriodicTask,这意味着任务将每(LOCATION_UPDATE_PERIOD * 60)秒执行一次。

听起来,默认的setUpdateCurrent=false是您想要的,您可以在BOOT_COMPLETED和您的onCreate()中为您的应用程序安排PeriodicTask。

如果您担心在第一次启动时希望立即更新位置,然后默认为每秒钟更新一次,则可以在onCreate中编写代码以:检查第一次启动(可能是写入shared_prefs文件,如果值不存在,则知道它是第一次启动)如果第一次启动,则安排一个特殊的OneoffTask在下一分钟执行。给这个OneoffTask一个像"LocationSchedulerService:first_boot“这样的特殊标签

然后在您的LocationSchedulerService中扩展GcmTaskService:

代码语言:javascript
复制
public int onRunTask{
    if (tag.equals("LocationSchedulerService:first_boot")) {
        performLocationUpdate();
        // Now that you've done the one time update, fall back to
        // your original schedule

        PeriodicTask task = new PeriodicTask.Builder()
            .setTag("LocationSchedulerService")
            .setService(LocationSchedulerService.class)
            .setPeriod(LOCATION_UPDATE_PERIOD * 60)
            .setFlex(LOCATION_UPDATE_FLEX * 60)
            .setPersisted(false)
            .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED)  // not needed, default
            .setRequiresCharging(false)  // not needed, default
            .setUpdateCurrent(true) // not needed, you know this is 1st time
            .build();

            GcmNetworkManager.getInstance(context).schedule(task);
    } else if tag.equals("LocationSchedulerService") {
        performLocationUpdate();
    } else {
        // error
    }

顺便说一句,您不需要BOOT_COMPLETED接收器。GcmNetworkManager的思想是允许您通过设置persisted=true来避免这种情况。这样,您就可以知道您的任务将在重新启动过程中持久化。通常只需在onCreate中安排一次就足够了。

票数 3
EN

Stack Overflow用户

发布于 2015-06-03 12:39:21

从文档中可以看出,调用setUpdateCurrent(true)将使用相同的标记更新PeriodicTask的调度约束。

可选的setter指定此任务是否应覆盖任何具有相同标记的预先存在的任务。这默认为false,这意味着新任务不会覆盖现有任务。

另外,您还可以在使用Task计划新的GcmNetworkManager.cancelTask()之前取消您的GcmNetworkManager.cancelTask()

票数 4
EN

Stack Overflow用户

发布于 2015-07-11 16:44:35

因为您的目标是让GcmTaskService始终运行,包括通过重新启动,所以您所需要做的就是setPersisted(true),而不是问题中的示例代码中的错误。

来自文档

公共PeriodicTask.Builder setPersisted (布尔isPersisted) 可选的setter指定此任务是否应在重新启动时持久化。对于周期性任务,这默认为true,调用方必须持有权限android.Manifest.permission.RECEIVE_BOOT_COMPLETED,,否则此设置程序将被忽略。

所以,不要担心自己的BootBroadcastReceiver,只需添加引导权限即可。

因为主要的问题是防止GcmTaskService同时多次运行。这可以通过对任务使用相同的标记来完成。默认情况下,如果任务(同名)已经在运行,那么就会发生。通过执行setUpdateCurrent(true),任务的参数将在调用schedule()时被更新/替换。

来源:PeriodicTask.Builder.setUpdateCurrent(boolean)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30619582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档