24

我正在使用以下代码使用 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 min * number 的线性退避策略会在作业失败的情况下失败。

我的工作服务代码如下所示:

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 被调用两次?

4

2 回答 2

26

在经历了很多挫折之后,我弄清楚了导致这个问题的原因。

您不应该要求定期jobFinished(JobParameters, true)工作。传递trueforneedsReschedule将导致该作业在队列中重复(您希望它覆盖原始作业,但显然情况并非如此)。jobFinished(JobParameters, false)即使您的任务失败,您也必须始终使用。

至于这是否算作错误的 API 使用或 Android 错误,我将由您决定。

于 2016-06-02T10:59:38.733 回答
3

由于 JobScheduler 将更多地与 Android Oreo 一起使用,因此我想描述该示例的一些问题:

onStopJob()覆盖的方法只返回true. 如果您的工作在处理过程中被中断,即充电器被拔掉或 JobInfo 中设置的没有网络,则应使用此功能也立即取消任务/工作。然后它应该返回true指示需要重新安排作业。

MyJobService应该有对任务的private参考。设置它。使用它来立即取消任务。MyWorkeronStartJob()onStopJob()

通常不需要在方法内传递true,尤其是在您的任务中调用时。如果作业中断,将调用 onStopJob() 取消它,返回 true 将重新安排它。我在这里只看到一个示例,其中设置为. 如果不满足先决条件的双重检查,则在and 范围内,然后代替.needsReschedulejobFinished()needsRescheduletrueonStartJob()jobFinished(args, true)return falsetrue

希望这可以帮助!

于 2017-08-09T23:10:55.063 回答