我创建了一个非常简单的服务来更新服务器上的用户位置:
public class LocationSchedulerService extends GcmTaskService {
@Override
public int onRunTask(TaskParams taskParams) {
// Update to server stuff
return GcmNetworkManager.RESULT_SUCCESS;
}
}
我创建了一个简单的BootBroadcastReceiver来在设备启动时启动服务:
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的文档,但我不确定功能性。这是否意味着当前正在运行的服务将被取消,或者它正是我想要的东西?
答案 0 :(得分:4)
从文档中看来,调用setUpdateCurrent(true)
似乎会更新PeriodicTask
的日程安排限制,并使用相同的标记。
可选的setter,用于指定此任务是否应覆盖具有相同标记的任何预先存在的任务。默认为false,这意味着新任务不会覆盖现有任务。
另外,您可以在使用GcmNetworkManager.cancelTask()
安排新的Task
之前取消ImpactEntity
答案 1 :(得分:3)
你所描述的是为什么引入了setUpdateCurrent - 应用程序想要一种方法“只安排他们的任务,如果它还不存在”
但你怎么说“我怎么防止任务运行两次”?您正在安排PeriodicTask,这意味着该任务将每隔(LOCATION_UPDATE_PERIOD * 60)秒执行。
听起来默认的setUpdateCurrent = false就是您想要的,并且您在应用程序的onCreate()中的BOOT_COMPLETED 和上安排了PeriodicTask。
如果您担心首次启动时要立即更新位置,然后默认为每个LOCATION_UPDATE_PERIOD * 60秒,则可以将onCreate中的代码写入: 检查第一次启动(可能写入shared_prefs文件,如果该值不存在,那么你知道它是第一次启动) 如果第一次启动,安排一个特殊的OneoffTask在下一分钟执行。给这个OneoffTask一个特殊的标签,比如“LocationSchedulerService:first_boot”
然后在您的LocationSchedulerService中扩展GcmTaskService:
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中安排一次就足够了。
答案 2 :(得分:1)
由于您的目标是始终运行GcmTaskService
,包括重新启动,您需要做的只是setPersisted(true)
,而不是问题示例代码中的错误。
来自docs:
public PeriodicTask.Builder setPersisted(boolean isPersisted)
可选的setter,用于指定是否应在重新引导后保留此任务。对于定期任务,此默认值为true,调用者必须持有权限android.Manifest.permission.RECEIVE_BOOT_COMPLETED,否则将忽略此setter。
所以,不要担心制作自己的BootBroadcastReceiver,只需添加启动权限。
由于主要问题是关于同时防止多次运行GcmTaskService
...可以通过为任务添加相同的标记来完成。默认情况下,如果任务(通过相同名称)已在运行,则会发生。通过执行setUpdateCurrent(true)
,在调用schedule()
时将更新/替换任务的参数。