Does .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) trigger a job to run IMMEDIATELY there is wifi

Viewed 1376

Does .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) actually TRIGGER the job to run immediately when the wifi comes back or will the job just run as part of another scheduled batch of jobs IF wifi happens to be available.

The only reason I ask is that since i have been experimenting it seems to have done both things. With Nougat for example it seems to actually trigger the job to run immediately when wifi comes back, whereas with with Lollipop (I think) it seemed like it just waited for another batch of jobs to run.

Kind of an important detail because if it doesn't trigger a job to run consistently on all verisons then I need a broadcast receiver to run my uploads when WIFI comes back.

1 Answers

Not necessarily. With JobScheduler, you are giving control over to Android to decide the best time to run something. However, the JobSchedulerService.java code has an explanation in the comments of the maybeQueueReadyJobsForExecutionLockedH method:

/**
 * The state of at least one job has changed. Here is where we could enforce various
 * policies on when we want to execute jobs.
 * Right now the policy is such:
 * If >1 of the ready jobs is idle mode we send all of them off
 * if more than 2 network connectivity jobs are ready we send them all off.
 * If more than 4 jobs total are ready we send them all off.
 * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
 */

This tells me that if I have two jobs waiting for the network, then they will run when the network comes on. I tested that and found it to be true. This was helpful, but I didn't necessarily want to wait for two jobs to queue and it sounds like you don't either.

I finally found that I can get more control over when it runs by also calling SetOverrideDeadline. By setting the deadline, it will run the job even if the network criteria is not met just that initial time. Obviously, your code would have to be smart enough to handle running without a connection, but then after that initial try, it then waits until ALL the criteria are all met to try again. The reason for that is not in the comment above (though it should be), but it is found in the actual code of that method. It turns out that if there are any jobs that had a previous failure, the job scheduler will run. Here is the relevant snippet from that same maybeQueueReadyJobsForExecutionLockedH method:

for (int i=0; i<jobs.size(); i++) {
    JobStatus job = jobs.valueAt(i);
    if (isReadyToBeExecutedLocked(job)) {
        if (job.getNumFailures() > 0) {
            backoffCount++;
        }
... 

Above notice the backoffCount being incremented, so that counts the total number of jobs that had previous failures. Then a few lines later:

if (backoffCount > 0 ||
        idleCount >= MIN_IDLE_COUNT ||
        connectivityCount >= MIN_CONNECTIVITY_COUNT ||
        chargingCount >= MIN_CHARGING_COUNT ||
        runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
    ... run the jobs ...
    }

I hope this saves you some time - I struggled for a while with this!

Related