Android 防止两次启动GcmTaskService
我创建了一个非常简单的服务,用于更新服务器上的用户位置:Android 防止两次启动GcmTaskService,android,google-play-services,Android,Google Play Services,我创建了一个非常简单的服务,用于更新服务器上的用户位置: public class LocationSchedulerService extends GcmTaskService { @Override public int onRunTask(TaskParams taskParams) { // Update to server stuff return GcmNetworkManager.RESULT_SUCCESS; } }
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(true)
将使用相同的标记更新PeriodicTask
的调度约束
可选设置程序,用于指定此任务是否应覆盖具有相同标记的任何先前存在的任务。这默认为false,这意味着新任务不会覆盖现有任务
此外,您还可以在计划新任务之前取消您的
任务
,如您所述,这就是引入setUpdateCurrent的原因-应用程序需要一种方法“仅在任务不存在时计划任务”
但是“如何防止任务运行两次”是什么意思?您正在计划PeriodicTask,这意味着任务将每隔(位置更新周期*60)秒执行一次
听起来您需要的是默认的setUpdateCurrent=false,您可以在启动完成时以及在应用程序的onCreate()中安排周期任务
如果您担心的是,在第一次启动时,您希望立即更新位置,然后默认为每个位置更新周期*60秒,那么您可以在onCreate中编写代码:
检查第一次引导(可能写入共享的\u prefs文件,如果该值不存在,则您知道这是第一次引导)
如果是第一次启动,则计划在下一分钟执行一个特殊的OneoffTask。给这个OneoffTask一个特殊的标签,比如“LocationSchedulerService:first\u boot”
然后在您的位置SchedulerService扩展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
}
顺便说一下,你不需要一个开机完成的接收器。GcmNetworkManager的思想是通过设置persisted=true来避免这种情况。这样,您就知道您的任务将在重新启动期间持久化。
通常只需在onCreate中安排一次就足够了。因为您的目标是始终运行
gcmtasksservice
,包括通过重新启动,所以只需执行setpersistend(true)
,而不是问题中的示例代码中的false
从:
public PeriodicTask.Builder setPersisted(布尔值isPersisted)
可选的setter,用于指定此任务是否应在重新启动期间持久化。对于定期任务,此默认值为true。调用者必须持有android.Manifest.permission.RECEIVE\u BOOT\u COMPLETED权限,否则将忽略此setter
因此,不必担心制作自己的BootBroadcastReceiver,只需添加引导权限即可
因为主要问题是防止同时运行
gcmtasksservice
。。这可以通过为任务使用相同的标记来实现。默认情况下,如果任务(同名)已在运行,则将发生。通过执行setUpdateCurrent(true)
,调用schedule()
时任务的参数将被更新/替换
来源:谢谢,我会在每次应用程序启动时再次安排作业(使用setUpdateCurrent),有一点副作用是每次都会将下一次执行时间重置回我的位置\u更新\u周期。但是这不是什么大问题。Philip,如果你这样做,那么你应该设置DateCurrent(false)(实际上这是默认设置)。这样做的目的是,每次应用程序启动时,您都可以调用schedule(),但不会将时间推到最后。这正是setter存在的原因。如果任务未计划(首次安装),则会将其插入。谢谢您的完整回答。现在我删除了BOOT_RECEIVED permission和receiver。@PhilipGiuliani重新启动后,GcmNetworkManager仍需要BOOT_RECEIVED permission才能继续执行任务。