Before Android Lollipop 5.0, there was just one solution to schedule tasks on Android. You must use the AlarmManager system service acquired thanks to the following method call : (AlarmManager) getSystemService(Context.ALARM_SERVICE);

The AlarmManager was functional but had some major disadvantages. First, it doesn’t consider if the device is connected to a power plug, idle or connected to a unmetered network. To solve these problems and improve battery life, Google has defined a new API with Android Lollipop grouped in the JobScheduler API.


Use cases

Job scheduling is useful in such situations as :

– App need a task that is non-user-facing and that you can defer.
– App has some long tasks that you prefer to process when device is plugged in.
– App has a task that needs a lot of network bandwith and you prefer that task be processed when device has Wi-Fi connection.
– App has number of tasks that you want to run in batch mode on a regular schedule.

 

Control execution’s conditions

With new API, a task is considered like a unit of work and is encapsulated in a JobInfo object. This object lets you to specify some criteria that you want for task execution.

You can define these criteria thanks to JobInfo.Builder class and so, you can configure how the scheduled task should run. You can define following specific conditions :

– Start only if device is charging.
– Start when the device is connected to an unmetered network like Wi-Fi.
– Start when the device is idle to avoid to slow down user’s work.
– Finish before a certain deadline or within a minimum delay.

 

Practice

Don’t forget that JobScheduler API has been introduced with Android 5.0. So, you need to use to use API Version 21 to use it. First, you need to define your task. A unit of work is defined by extended JobService class that is in the android.app.job package.

We can define a job like that :


package com.ssaurel.jobscheduler.sample;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.os.AsyncTask;

public class MyJob extends JobService {

 private JobParameters params;
 private MyLargeTask largeTask;

 @Override
 public boolean onStartJob(JobParameters params) {
   // get param to use if if needed ...
   this.params = params;
   largeTask = new MyLargeTask();
   largeTask.execute();
   return false;
 }

 @Override
 public boolean onStopJob(JobParameters params) {
   if (largeTask != null)
     largeTask.cancel(true);

   return false;
 }

  // large task used ...
  private class MyLargeTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected void onPostExecute(Void aVoid) {
      jobFinished(params, false);
      super.onPostExecute(aVoid);
    }

    @Override
    protected Void doInBackground(Void... params) {
      // long task process here ...
      return null;
    }
 }

}

 

Now, we can schedule our job under specific conditions. Here, we want an execution only if device is in charging with an unmetered network connection :


ComponentName componentName = new ComponentName(getApplicationContext(), MyJob.class);
JobInfo jobInfo = new JobInfo.Builder(1, componentName).setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED).setRequiresCharging(true).build();
JobScheduler jobScheduler = (JobScheduler) getApplicationContext().getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);

 

In that code, you can see that JobInfo.Builder lets you to configure conditions of execution for MyJob task. Before that, you can get JobScheduler system service thanks to a getSystemService call. Then, you schedule the task by calling schedule method.