我使用以下代码使用Androids JobScheduler API创建和安排作业:
Log.d("hanif", "Scheduling periodic job 2 hrs with 20 mins backoff linear");
JobInfo jobInfo = new JobInfo.Builder(JOB_ID,
new ComponentName(getApplicationContext(), MyJobService.class))
.setPeriodic(TimeUnit.HOURS.toMillis(2))
.setRequiresCharging(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setBackoffCriteria(TimeUnit.MINUTES.toMillis(20),
JobInfo.BACKOFF_POLICY_LINEAR)
.build();
JobScheduler scheduler =
(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
即。一个每2小时执行一次的定期工作,如果工作失败,则执行20分钟*的线性退避政策会失败。
我的工作服务代码如下:
public class MyJobService extends JobService {
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d("hanif", "onStartJob");
new MyWorker(getApplicationContext(), this, jobParameters).execute();
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d("hanif", "onStopJob");
return true;
}
private static class MyWorker extends AsyncTask<Void, Void, Boolean> {
private final Context mContext;
private final MyJobService mJobService;
private final JobParameters mJobParams;
public MyWorker(Context context, MyJobService myJobService, JobParameters jobParameters) {
mContext = context;
mJobService = myJobService;
mJobParams = jobParameters;
}
@Override
protected Boolean doInBackground(Void... voids) {
Log.d("hanif", "Work start!");
for (int i=0; i<999999999; i++) {}
int counter = Prefs.getCounter(mContext);
Log.d("hanif", "Work done! counter: " + counter);
if (counter == 3) {
Log.d("hanif", "DO RESCHEDULE");
Prefs.resetCounter(mContext);
return true;
}
Log.d("hanif", "DO NOT RESCHEDULE");
Prefs.increaseCounter(mContext);
return false;
}
@Override
public void onPostExecute(Boolean reschedule) {
if (reschedule) {
mJobService.jobFinished(mJobParams, true);
} else {
mJobService.jobFinished(mJobParams, false);
}
Log.d("hanif", "------------------------------------------");
}
}
}
最后日志输出如下:
03-27 12:57:11.677 7383 7383 D hanif : Scheduling periodic job 2 hrs with 20 mins backoff linear
03-27 12:57:31.904 7383 7383 D hanif : onStartJob
03-27 12:57:31.909 7383 8623 D hanif : Work start!
03-27 12:57:42.110 7383 8623 D hanif : Work done! counter: 0
03-27 12:57:42.111 7383 8623 D hanif : DO NOT RESCHEDULE
03-27 12:57:42.125 7383 7383 D hanif : ------------------------
03-27 14:58:50.786 7383 7383 D hanif : onStartJob
03-27 14:58:50.789 7383 21490 D hanif : Work start!
03-27 14:59:00.952 7383 21490 D hanif : Work done! counter: 1
03-27 14:59:00.953 7383 21490 D hanif : DO NOT RESCHEDULE
03-27 14:59:00.962 7383 7383 D hanif : ------------------------
03-27 16:57:12.021 7383 7383 D hanif : onStartJob
03-27 16:57:12.045 7383 32028 D hanif : Work start!
03-27 16:57:22.229 7383 32028 D hanif : Work done! counter: 2
03-27 16:57:22.230 7383 32028 D hanif : DO NOT RESCHEDULE
03-27 16:57:22.238 7383 7383 D hanif : ------------------------
03-27 18:57:11.984 7383 7383 D hanif : onStartJob
03-27 18:57:11.989 7383 13217 D hanif : Work start!
03-27 18:57:22.123 7383 13217 D hanif : Work done! counter: 3
03-27 18:57:22.124 7383 13217 D hanif : DO RESCHEDULE
03-27 18:57:22.130 7383 7383 D hanif : ------------------------
03-27 19:20:57.468 7383 7383 D hanif : onStartJob
03-27 19:20:57.482 7383 1913 D hanif : Work start!
03-27 19:21:07.723 7383 1913 D hanif : Work done! counter: 0
03-27 19:21:07.724 7383 1913 D hanif : DO NOT RESCHEDULE
03-27 19:21:07.733 7383 7383 D hanif : ------------------------
03-27 19:21:57.669 7383 7383 D hanif : onStartJob <--- Why is this called again?
03-27 19:21:57.675 7383 3025 D hanif : Work start!
03-27 19:22:07.895 7383 3025 D hanif : Work done! counter: 1
03-27 19:22:07.896 7383 3025 D hanif : DO NOT RESCHEDULE
03-27 19:22:07.906 7383 7383 D hanif : ------------------------
03-27 21:40:53.419 7383 7383 D hanif : onStartJob
03-27 21:40:53.423 7383 31526 D hanif : Work start!
03-27 21:41:03.857 7383 31526 D hanif : Work done! counter: 2
03-27 21:41:03.858 7383 31526 D hanif : DO NOT RESCHEDULE
03-27 21:41:03.867 7383 7383 D hanif : ------------------------
为什么onStartJob会被调用两次?
答案 0 :(得分:18)
非常沮丧之后,我想出了导致这个问题的原因。
您应该不在定期工作中致电jobFinished(JobParameters, true)
。为true
传递needsReschedule
将导致作业在队列中重复(您可能希望它覆盖原始作业,但显然情况并非如此)。即使您的任务失败,您也必须始终使用jobFinished(JobParameters, false)
。
至于这是否算作错误的API使用或Android错误,我会把它留给你。
答案 1 :(得分:1)
由于JobOcheduler将在Android Oreo中得到更多使用,我想用这个例子描述一些问题:
onStopJob()
重写方法仅返回true
。如果您的作业在处理过程中被中断,即拔出充电器或没有JobInfo中设置的网络,则应使用此功能立即取消任务/作业。然后它应该返回true
,表明需要重新安排工作。
MyJobService
应该private
引用MyWorker
任务。 onStartJob()
设置它。 onStopJob()
使用它立即取消任务。
通常不需要在true
方法中为needsReschedule
传递jobFinished()
,尤其是在您的任务中调用时。如果作业中断,将调用onStopJob()取消它,返回true将重新计划它。我只看到一个示例here,其中needsReschedule
设置为true
。它在onStartJob()
之内,如果不满足前提条件的重复检查,则jobFinished(args, true)
然后return false
而不是true
。
希望这有帮助!