Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

This tutorial describes how to schedule tasks in Android with the JobScheduler API.

1. Scheduling tasks

1.1. How not to do it

If you have a repetitive task in your Android app, you need to consider that activities and services can be terminated by the Android system to free up resources. Therefore you can not rely on standard Java schedule like the TimerTasks class.

1.2. Options for scheduling

The Android system currently has two main means to schedule tasks:

  • the (outdated) AlarmManager

  • the JobScheduler API.

Modern Android apps should use the JobScheduler API. Apps can schedule jobs while letting the system optimize based on memory, power, and connectivity conditions.

2. Using the JobScheduler to schedule background jobs

2.1. The job scheduler API

The Android 5.0 Lollipop (API 21) release introduces a job scheduler API via the JobScheduler class. This API allows to batch jobs when the device has more resources available. In general this API can be used to schedule everything that is not time critical for the user.

2.2. Advantages of the job scheduler API

Compared to a custom SyncAdapter or the alarm manager, the JobScheduler supports batch scheduling of jobs. The Android system can combine jobs so that battery consumption is reduced. JobManager makes handling uploads easier as it handles automatically the unreliability of the network. It also survives application restarts. Here are example when you would use this job scheduler:

  • Tasks that should be done once the device is connect to a power supply

  • Tasks that require network access or a Wi-Fi connection.

  • Task that are not critical or user facing

  • Tasks that should be running on a regular basis as batch where the timing is not critical

2.3. Create a Job

A unit of work is encapsulated by a JobInfo object. This object specifies the scheduling criteria. The job scheduler allows to consider the state of the device, e.g., if it is idle or if network is available at the moment. Use the JobInfo.Builder class to configure how the scheduled task should run. You can schedule the task to run under specific conditions, such as:

  • Device is charging

  • Device is connected to an unmetered network

  • Device is idle

  • Start before a certain deadline

  • Start within a predefined time window, e.g., within the next hour

  • Start after a minimal delay, e.g., wait a minimum of 10 minutes

These constraints can be combined. For example, you can schedule a job every 20 minutes, whenever the device is connected to an unmetered network. Deadline is a hard constraint, if that expires the job is always scheduled.

To implement a Job, extend the JobService class and implement the onStartJob and onStopJob. If the job fails for some reason, return true from on the onStopJob to restart the job. The onStartJob is performed in the main thread, if you start asynchronous processing in this method, return true otherwise false.

3. Exercise: Using the JobScheduler to schedule background jobs

3.1. Target of this exercise

In this exercise you build a small example application to schedule jobs via the JobScheduler API.

3.2. Create project and layout file

Create a new Android project called com.vogella.android.jobscheduler based on API 21.

Create a layout file with at least one button. Assign the onClick method to the onClick property of the button.

3.3. Create the JobService

Create a service with the following implementation.

package com.vogella.android.jobscheduler;

import java.util.LinkedList;

import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

/**
 * JobService to be scheduled by the JobScheduler.
 * Requests scheduled with the JobScheduler call the "onStartJob" method
 */
public class TestJobService extends JobService {
        private static final String TAG = "SyncService";

        @Override
        public boolean onStartJob(JobParameters params) {
                // fake work
                Log.i(TAG, "on start job: " + params.getJobId());
                return true;
        }

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

}
Ensure you register it via your Android manifest.

3.4. Create test activity

Change your activity implementation to the following code.

package com.vogella.android.jobscheduler;

import android.app.Activity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;

public class MainActivity extends Activity {
        TestJobService testService;
        private static int kJobId = 0;

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        }

        public void onClick(View v) {
                ComponentName mServiceComponent = new ComponentName(this, TestJobService.class);
                JobInfo.Builder builder = new JobInfo.Builder(kJobId++, serviceComponent);
                builder.setMinimumLatency(5 * 1000); // wait at least
                builder.setOverrideDeadline(50 * 1000); // maximum delay
                builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); // require unmetered network
                builder.setRequiresDeviceIdle(true); // device should be idle
                builder.setRequiresCharging(false); // we don't care if the device is charging or not
                JobScheduler jobScheduler = getApplication().getSystemService(Context.JOB_SCHEDULER_SERVICE);
                jobScheduler.schedule(builder.build());
        }

        public void cancelAllJobs(View v) {
                JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
                tm.cancelAll();
        }


}

4. Exercise: Use JobScheduler from a receiver

4.1. Target of this exercise

We demonstrate how to trigger a job which triggers a service from a broadcast receiver.

4.2. Create the receiver

Create the following receiver

package com.example.android.rssreader;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        ComponentName serviceComponent = new ComponentName(context, MyJobService.class);
        JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
        builder.setMinimumLatency(5 * 1000); // wait at least
        builder.setOverrideDeadline(50 * 1000); // maximum delay
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); // require unmetered network
        builder.setRequiresDeviceIdle(true); // device should be idle
        builder.setRequiresCharging(false); // we don't care if the device is charging or not
        JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
        jobScheduler.schedule(builder.build());

    }
}

4.3. Create your job

package com.example.android.rssreader;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;

/**
 * Created by vogella on 30.06.16.
 */

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {
        String url = params.getExtras().getString(RssApplication.URL);
        Intent i = new Intent(this, RssDownloadService.class); // starts the RssDownloadService service
        i.putExtra(RssApplication.URL, url); // some extra data for the service
        startService(i);
        return false; // true if we're not done yet
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        // true if we'd like to be rescheduled
        return true;
    }


}

You can register your receiver for an event, e.g., the boot completely event. It will trigger the receiver, which registers the job which starts your custom service

5. About this website

6. Links and Literature

Nothing listed.

6.1. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.