Android JobScheduler执行了好几次

时间:2016-03-21 16:09:12

标签: java android android-jobscheduler

我使用以下代码使用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会被调用两次?

2 个答案:

答案 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

希望这有帮助!