Easy Job Scheduling with Android-Job

Rajesh Pattanaik
AndroidPub
Published in
5 min readMar 26, 2017

--

In the modern app development era, running some background tasks outside the scope of an application’s life-cycle have become one of the key requirements. These tasks may be as simple as just reminding the user of something or as complex as syncing local data with server and fetching latest data periodically to provide better user experience. Implementing these features in Android is really challenging and you have to be very careful with your app performance along with other aspects such as battery life.

Android provides several APIs for scheduling background work (beyond the app life-cycle).

  1. JobScheduler

JobScheduler was introduced in Lollipop and its the most efficient way to perform background work, especially networking. It performs background work based on conditions, not on time. These conditions may be whether the device is connected to a network, charging or idle.

JobScheduler comes with a very fluent API and its very easy to implement. You can use JobScheduler by registering jobs specifying their requirements for network and timing. Then the system schedules the jobs to run at appropriate times. It also defers the execution as necessary to comply with Doze mode and App Standby restrictions. Also the jobs are batched together by the system to save battery life. Another handy feature is that the scheduled jobs are persisted through system reboots.

JobScheduler is the way to go with API if your app targets Lollipop (API level 21) and above.

Source: developer.android.com

2. GCM Network Manager

GCM Network Manager comes with a similar API like JobScheduler and it targets API level 9 and above. It uses JobScheduler behind the scene for API level 21 and higher. It has all the battery saving scheduling features from JobScheduler.

The main disadvantage with GCMNetworkManager is its a part of Google’s Play Services SDK and can be used only on devices with Google Play preinstalled. Another gotcha is that all scheduled Services will be wiped out when the application or Google Play Service updates.

3. AlarmManager

Though JobScheduler and GCMNetworkManager are good at performing tasks based on conditions such as network connectivity, device charging etc while keeping battery life in mind, they are not meant for performing tasks immediately or at a specific time. An Alarm Clock or Reminder App which needs precision in timing should not use any of these options. Instead use AlarmManager when your app needs to post a notification or set off an alarm at a very specific time.

The AlarmManager is typically used to fire off a PendingIntent that will start a Service in the future. It has the ability to wake up the device if the alarm is urgent. We can use AlarmManager for periodic tasks based on an elapsed time interval. The main gotcha with AlarmManager is that the API behavior differs between platform versions. There’s a lot of boilerplate required to implement AlarmManager. Also the device state is ignored.

Never use AlarmManager to perform networking tasks.

As you can see, scheduling background work in Android is quite a headache with 3 different APIs all performing the same thing. To overcome this problem, the nice folks at Evernote have open sourced a unified library to schedule jobs in Android.

Meet Android-Job

  • Android-Job abstracts away which implementation you want to use to perform background work.
  • Depending on the requirements, this library decides which API to use to run your job.
  • It provides a superset of all the features from JobScheduler, GCMNetworkManager and AlarmManager.
  • All features from Android Nougat are backward compatible.
  • Less boilerplate.

Setting up Android-Job

Include android-job dependency in your app module’s build.gradle file and sync project.

Using Android-Job

Implementing Android-Job is super easy.

The API includes below classes/interfaces.

  1. Job: Your jobs need to extend this class and override onRunJob method. The heavy lifting is done here. You must return a Result from this method so that the system knows whether to attempt to run your job at a later time.
  2. JobRequest: You can schedule a Job by creating a JobRequest using its builder constructor and passing your Job tag.
  3. JobCreator: JobCreator acts like a factory to provide a Job based on a job tag. Your concrete JobCreator class must implement the JobCreator interface and override the create method.
  4. JobManager: The JobManager class serves as the entry point. Before using this class you must initialize this as singleton. JobManager takes a Context. After creating the instance, you have to add your JobCreator to JobManager.

Here we will develop a simple app to show notification to the user periodically.

Let’s create our ShowNotificationJob class in the first step.

In the onRunJob method we are simply showing a notification and we are returning Result.SUCCESS every time the job runs.

Also we have a static schedulePeriodic method which builds the JobRequest through its Builder and schedules the job by calling schedule(). We are passing ShowNotificationJob.TAG in the Builder constructor which tells our JobCreator to return a ShowNotificationJob instance.

JobRequest.Builder has many methods. Here we are calling setPeriodic to tell the system that this is a periodic job which runs every 15 minutes. Also we have passed 5 minutes as the 2nd parameter which is actually the flex time. This helps the system to batch our job with any other jobs with similar time interval.

setUpdateCurrent(true) will update the current job instead of creating a new job.

setPersisted(true) tells the system to persist the job through system reboots.

Next let’s create our DemoJobCreator class which implements JobCreator interface.

As you can see, in the create method we have a switch construct which maps a tag with a specific job.

In the next step we will create our MainApp class which extends Application class. In the MainApp class we will create the JobManager instance by passing our application context and add our DemoJobCreator to the JobManager.

In the final step we will call the schedulePeriodic method of our ShowNotificationJob class in the onCreate method of MainActivity to schedule our job when our application starts.

That’s it.

You can implement your Job using this library very easily. You can create a much advanced job by creating JobRequest as per your requirements. You can see all the methods available for creating an advanced job in their github repo.

Please visit this link for all the details about the API.

For our demo app please visit below link.

Bonus — Debugging Tip

While debugging, you may set the interval time to 1 minute or less to test the app quickly. But in Android N the minimum interval of periodic jobs is 15 minutes. So you will get this error while running the job.

intervalMs is out of range

To overcome this error you can configure the JobManager with setAllowSmallerIntervalsForMarshmallow(true) method for debugging purpose. But remember, in production you must set the minimum interval time to 15 times otherwise your app may behave differently in different platform versions.

Please like, share and tweet this article to show your love which will encourage me to write more articles on better android development.

--

--