Periodic JobScheduler doesn't respect constrai

2020-04-10 01:26发布

问题:

Using the JobScheduler, I set up a simple JobService as follows:

@TargetApi(21)
public class SimpleJobService extends JobService {
    private static final String TAG = "SimpleJobService";

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        if (jobParameters.isOverrideDeadlineExpired()) {
            Log.d(TAG, "This shouldn't happen");
            Toast.makeText(this, "This shouldn't happen", Toast.LENGTH_LONG).show();
        }
        jobFinished(jobParameters, false);

        return true;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        return true;
    }
}

I then setup the JobService to be periodic (every minute) and require unmetered network and charging:

    ComponentName jobServiceComponent = new ComponentName(this, SimpleJobService.class);

    JobInfo.Builder builder = new JobInfo.Builder(2, jobServiceComponent);
    builder.setPersisted(true);
    builder.setPeriodic(60000);
    builder.setRequiresCharging(true);

    builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
    JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
    jobScheduler.schedule(builder.build());

The onStartJob of my SimpleJobService is being called regardless of whether my device is charging or if it's on an unmetered network.

The documentation for setPeriodic(long) says it can't be used in conjunction with setOverrideDeadline(long) (and I'm not anyway), but I'm surprised that jobParameters.isOverrideDeadlineExpired() in onStartJob is ever true with this setup.

Am I missing something here?

This looks like an Android bug to me, but I'm surprised I couldn't find other people reporting this issue.

This behaviour was observed on Android 6.0.1

回答1:

A periodic job has an implicit deadline of the end of the period as seen in the source code.

Just like explicitly setting a deadline, this gives you an opportunity to decide on how best to handle extended periods of time (you'll note there is a minimum interval, queryable on Android 7.0+ devices with getMinPeriodMillis()) when your conditions are not met. For example, if your constraints are hard requirements, you can call jobFinished(jobParameters, false) to wait for the next periodic end point or the conditions to be true.