Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Asynchronous Android Programming - Second Edition

You're reading from  Asynchronous Android Programming - Second Edition

Product type Book
Published in Jul 2016
Publisher Packt
ISBN-13 9781785883248
Pages 394 pages
Edition 2nd Edition
Languages
Author (1):
Steve Liles Steve Liles
Profile icon Steve Liles

Table of Contents (19) Chapters

Asynchronous Android Programming Second Edition
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
1. Asynchronous Programming in Android 2. Performing Work with Looper, Handler, and HandlerThread 3. Exploring the AsyncTask 4. Exploring the Loader 5. Interacting with Services 6. Scheduling Work with AlarmManager 7. Exploring the JobScheduler API 8. Interacting with the Network 9. Asynchronous Work on the Native Layer 10. Network Interactions with GCM 11. Exploring Bus-based Communications 12. Asynchronous Programing with RxJava Index

Chapter 7. Exploring the JobScheduler API

So far, we have been scheduling background work using a time condition in the Handler facilities for the short-term future, and the Android Alarm Manager for the long-term future.

Those APIs that are able to execute future tasks at an exact and inexact time in the future are used to trigger events, refresh data in the background, or execute tasks without user intervention. AlarmManager, which we covered in detail in the previous chapter, is able to wake up the device from deep idle states and execute work even without considering the device's battery state.

In this chapter, we will learn how to work with JobScheduler to execute jobs in the background when several prerequisites are fulfilled and taking into account the energy consumption context of the device.

In this chapter, we will cover the following:

  • Introduction to JobScheduler

  • Setting the JobScheduler running criteria

  • Controlling the execution of your job with criteria

  • How to schedule work with JobService...

Introduction to JobScheduler


The Android development team, under the project Volta umbrella, introduced in the API Level 21 Lollipop release some enhancements and features in order to improve the power usage on the Android platform. Apart from the tools introduced to monitor and follow the battery usage in the Android platform, a new API for scheduling background was officially released to help the developer. It saves extra power cycles when the jobs used to support the developer's application do not need a time of execution, and can be deferred until the device has better battery and network context.

The API was not created to completely replace AlarmManager; however, the JobScheduler API is able to perform a better battery management and supply extra behaviors.

The main features introduced with Scheduler API are as follows:

  • Less power consumption: The job task could be delayed until the device is powered to the charger or they are grouped to run in batches on a regular basis

  • Persistent jobs...

Setting running criteria


With the Builder object reference, we can start setting up the job parameters and the pre-requisites using the member function available in the Builder object.

Let's consider a couple of examples. In our first example, the job should only start when there is a Wi-Fi network available, so to achieve that, we have to use the following code to set the network availability pre-requisite:

jobIBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);

An unmetered network connection means that you have a connection where you don't have a limited amount of data usage per month and you are not charged when you go over the usage limit. When a network type is not specified, as a condition, the default value is NETWORK_TYPE_NONE, meaning that the job will run in any network context and even without any network connection. Apart from the previous network type criteria, there is NETWORK_TYPE_ANY, which determines that the job could run when there is network connectivity available...

Scheduling a job


With the criteria already defined and the JobInfo object, we have all the entities required to set up the job for our application. So now let's show you how to create a job with a real example.

Our example will synchronize the user account information stored in a device file with an HTTP web service over a job scheduled using the Scheduler API. The user interface will provide us a UI where we can update the user information, a button to save the information on an internal file, and a button to set up the synchronization job that will upload the account information to the web service.

First, let's start by defining our job pre-requisites and parameters:

  • Our job should only run when the device is charging to save the battery

  • Our job should only run when an unmetered network is available to save mobile network bandwidth

  • Our job should only run when the device is idle because we don't want to slow down the UI responsiveness

  • Our job must run at least once within eight hours of being...

Implementing the JobService


Our JobService subclass is the entity that is going to do the hard work and receive the callbacks as soon as all the criteria specified in the JobInfo are met. To implement our own service, we have to extend from JobService and override the start and stop callbacks, as shown in the following code:

public class AccountBackupJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {
      // Start your job here
        return false;
    } 
    @Override
    public boolean onStopJob(JobParameters params) {
        // Stop your job here
        return false;
    }
}

The onStartJob callback function runs on the main thread, and if the job needs to do asynchronous processing then it should return true to indicate it's still doing work on a background thread. The callback function also receives the extra parameters specified in the JobInfo bundle.

onStopJob is automatically invoked by the system when it requires to cancel the job...

Listing pending jobs


Unlike the AlarmManager API, the Scheduler API provides the ability to list all the pending schedules for your application. This handy feature could help us to recognize the jobs that are going to be executed in the future and react accordingly with that list. The list retrieved could help us to pinpoint a pending job that we would like to cancel.

The JobScheduler service class has an instance method with the following signature:

public List<JobInfo> getAllPendingJobs();

The method will return a list of JobInfo objects that we can use to observe job parameter sets during the job build:

  • Job criteria for each job:

    • getNetworkType()

    • isRequireDeviceIdle()

    • isRequireCharging()

    • getMinLatencyMillis()

    • isPeriodic()

    • getIntervalMillis()

    • isPersisted()

    • getMaxExecutionDelayMillis()

  • The JobService subclass that will be called back by the JobScheduler to execute the job—getService()

  • Job arguments: getExtras()

  • Retry policy: getInitialBackoffMillis() and getBackoffPolicy()

Okay...

Canceling a job


There are some situations where we want to provide for the users an ability to cancel the job because the environment situation has changed or it does not make sense to execute the job anymore—for example, the user changed a piece of information that the job depends on and the job is no longer applicable. The JobScheduler service offers us the support for job cancellation with the following cancel and cancelAll methods:

void cancel(int jobId);

void cancelAll();

The first method, cancel(jobId), allows us to cancel a specific job using the job identifier returned from the schedule(JobInfo job) function or the jobId available on JobInfo objects returned by the getAllPendingJobs function.

The cancelAll() method allows us to cancel the scheduled jobs that have been registered with the JobScheduler by the current application.

With JobInfo from the previous example we are able to cancel a specific job passing the job identifier:

  final JobInfo ji = ...;
  JobScheduler jobScheduler...

Scheduling a periodic job


So far, we have scheduled one-shot jobs, but do you know there is an option to schedule the execution of a job at periodic internals. These kinds of jobs might be the perfect construct to performing repeating backups or repeating network operations such as application user data backup.

Let's update our AccountInfoActivity to schedule the periodic execution of the account synchronization job.

We'll start by defining a new job identifier for our periodic job:

static final int SYNC_PER_JOB_ID = "SyncJobPerService".hashCode();

We can schedule a periodic job to be executed approximately every 12 hours like this:

JobInfo.Builder builder = new JobInfo.Builder(SYNC_PER_JOB_ID,
   serviceName);
builder.setRequiresDeviceIdle(true)  
  // Persist the schedule across the device reboots
  .setPersisted(true)
  .setPeriodic(TimeUnit.HOURS.toMillis(12L))
  .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
  .setRequiresDeviceIdle(true)
  .setExtras(bundle);
  
// Schedule the...

Applications of the JobScheduler


The JobScheduler API allows us to schedule work that runs asynchronously without user intervention in the future under certain conditions. This API is also able to reduce the energy consumption by deferring the job execution until the device is charging or connected to an unmetered network, such as the Wi-Fi network.

Ideal cases include things such as application database backup that could be deferred and do not require exact time execution, a periodic upload of user data to the network, and download of configuration parameters. So, typically jobs that don't have to run immediately and which data doesn't have to be ready for user consumption. Reducing your application energy consumption without compromising the user experience will increase the device battery lifetime and therefore improve the user experience.

The JobScheduler could cover most of the AlarmManager use cases, notwithstanding it provides advanced features to optimize device resources acquisition...

Summary


In this chapter, we explored the JobSheduler API, putting it to use to schedule background work that starts when a group of conditions defined by us are met.

We learned in detail how to set the different criteria supported by the API and how to schedule based on the JobInfo object that starts a job when the device is charging and not in use.

In the meantime, we learned how to implement an asynchronous JobService that is able to run in a background execution line and finish the job execution properly by releasing all the acquired resources (WakeLock, ...).

Later, we used the getAllPendingJobs to create a sample code to list all the pending Scheduler API jobs within our application. From the example, we learned how to cancel a specific job or all the pending jobs in our applications.

To finish, we built a persistent and recurrent schedule using the JobSheduler API, which wakes up the device and executes our job every 12 hours.

In the next chapter, we will learn how to transfer data from...

lock icon The rest of the chapter is locked
You have been reading a chapter from
Asynchronous Android Programming - Second Edition
Published in: Jul 2016 Publisher: Packt ISBN-13: 9781785883248
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at AU $19.99/month. Cancel anytime}