我想要实现的是后台服务,每小时从服务器获取数据。我希望这个服务可以在启动后定期运行。因此,我选择使用JobScheduler来实现此功能。
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val builder = JobInfo.Builder(1, ComponentName(this, PullDataJob::class.java))
.setPeriodic(1000L * 60 * 60) // one hour
.setRequiredNetworkType(NETWORK_TYPE_ANY)
.setPersisted(true)
jobScheduler.schedule(builder.build())
这是我当前的代码,位于onCreate()
内。但是,我发现如果我将JobScheduler.schedule()
放在onCreate()
中,则每次打开应用程序时都会自动执行该服务。
即使用户在系统启动后从未打开过应用程序,上面代码最好放在哪个位置以使服务定期运行?
答案 0 :(得分:1)
您的工作会定期执行(每小时一次),所以一旦第一次运行,JobScheduler.schedule()
永远将再次被调用。
完成此操作非常简单,一旦您第一次致电JobScheduler.schedule()
,请注册已安排好的事实,并且只有当您确定自己的工作有效时才会运行调度方法从来没有跑过。
public static final String IS_JOB_FIRST_RUN = "job scheduled";
...
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
if (preferences.getBoolean(IS_JOB_FIRST_RUN, true)) {
// your code
JobScheduler.schedule();
preferences.edit().putBoolean(IS_JOB_FIRST_RUN, false).apply();
}
答案 1 :(得分:0)
Hakeem是正确的,您只应安排一次。 如果您两次计划具有相同JobId的作业,则文档说明如下:
将用JobInfo中的新信息替换具有相同ID的任何当前计划的作业。如果具有给定ID的作业当前正在运行,它将停止。
但是我会解决不同于hakeem的问题。而不是将这些信息保存在Sharedpreference中,您应该使用JobScheduler来确定具有您ID的作业是否已被调度。这样,您会更健壮,并在发生一些奇怪的事情并且不再安排您的工作时会重新安排工作。
代码:
public static boolean isJobServiceOn( Context context ) {
JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE ) ;
boolean hasBeenScheduled = false ;
for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
if ( jobInfo.getId() == RETRIEVE_DATA_JOB_ID ) {
hasBeenScheduled = true ;
break ;
}
}
return hasBeenScheduled ;
}
在计划作业时,您可以仅使用此功能来确定我当前是否计划了该作业。