The new release of Android 5.0 provides developers over 5000 new APIs to play with.
One of my favourite component that was relseased with the new SDK is JobScheduler. Briefly:
JobScheduler API that lets you optimize battery life by defining jobs for the system to run asynchronously at a later time or under specified conditions.
Unfortunately, the JobScheduler API is only available for minSdkVersion 21 as it uses system components only available in Android 5.0.
Scheduling a job
In order to schedule a job you must define 2 components:
JobInfo
that holds the constraints of when the job should run (e.g. only on WiFi, only when plugged in, periodically, etc.)JobService
that is a service that handles the scheduled requests.
Lets start by defining our job constraints. Suppose we want to run a background task when the device is connected to WiFi and plugged in. In order to create our JobInfo
object we use the JobInfo.Builder
:
JobInfo job = new JobInfo.Builder(JOB_ID, new ComponentName(this, SyncJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
The JobInfo
needs an integer id and a service component that will be our implementation of JobService. In order to define our constraints we setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
in order the job to run only on WiFi connection and setRequiresCharging(true)
for the device to be plugged in. The only remaining part is to actually schedule the job:
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(job);
Upon calling jobScheduler.schedule(job)
the job will be executed if the criteria are met. If you want to make sure that your job will be executed after a period of time regardless of the state of the criteria specified when creating the job, you can use the setOverrideDeadline(long)
when building your JobInfo
object:
JobInfo job = new JobInfo.Builder(JOB_ID, new ComponentName(this, SyncJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.setOverrideDeadline(3600000) //the job will be executed anyway after one hour
.build();
There are a bunch of other parameters to play with when building your job, see them all here.
Creating the JobService
The JobService
is the entry point of executing your scheduled job. You create your service by extending JobService
and overriding the onStartJob(JobParameters jobParameters)
and onStopJob(JobParameters params)
callbacks. As their name suggest, the first callback is fired when the job starts - this is the place where the job logic should be implemented - and the second one when the job is stopped by the system because the criteria are not met anymore. You must take your job implementation from the onStartJob
callback on another thread as this method is called on the application's main thread.
Lets start by defining our JobService
in the AndroidManifest.xml
file:
<application ...>
...
<service
android:name="com.catinean.jobschedulerexample.SyncJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" />
...
</application>
Note that you must protect your service with the android.permission.BIND_JOB_SERVICE
permission in order the OS to not ignore it. A simple implementation of a JobService
would look like this:
public class SyncJobService extends JobService {
@Override
public boolean onStartJob(JobParameters jobParameters) {
new JobTask(this).execute(jobParameters);
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
private static class JobTask extends AsyncTask<JobParameters, Void, JobParameters> {
private final JobService jobService;
public JobTask(JobService jobService) {
this.jobService = jobService;
}
@Override
protected JobParameters doInBackground(JobParameters... params) {
SystemClock.sleep(5000);
return params[0];
}
@Override
protected void onPostExecute(JobParameters jobParameters) {
jobService.jobFinished(jobParameters, false);
}
}
}
As it can be seen in the above code snippet, when a job is scheduled to start, we execute an AsyncTask
that will sleep 5 seconds and then report that the job has finished.
Conclusion
The JobScheduler API is perfect when you want to run background non user-facing tasks when certain criteria are met. The only downside that I see for the moment is that JobScheduler is only available for api level 21 (Android 5.0).
You can find here a full working example based on the snippets above.