How to name-drop JobScheduler like a pro
Pro-tip by
+Joanna SmithIf you have some heavy work to do, and it doesn’t need to be done RIGHT NOW OMG NOW NOW, then I’m going to kindly ask you to use JobScheduler (
http://goo.gl/1mVGiv). Because it’ll get your job done, while using other jobs to intelligently schedule the work to minimize use of the radio, which is a clear battery win. So just do it. Please.
JobScheduler was introduced in Lollipop, and is pretty cool because it doesn’t perform work solely based on time, but rather based on conditions. You can define those conditions when you are creating the job, through the JobInfo object (
http://goo.gl/UNma9K). For example, you can use setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) for jobs that you want to execute when the user is on WiFi. Or you can use setPersisted(true) for jobs that you want to persist across a potential reboot. Or you can read the documentation to see how to play with other criteria you might care about, from back-off policies to time limits for scheduling the job. (Basically, this is where the magic happens, so spend some time getting this right.)
To build that JobInfo object, though, you need two things every time (the criteria are the bonus bits): a job number - to help you distinguish which job this is - and a JobService (
http://goo.gl/svz1hR). Your JobService is actually going to be a Service that extends the JobService class. Which means you need to implement a few methods:
+onStartJob() is called by the system when it is time for your job to execute. This is where the one tricky part about JobScheduler exists. Your JobService runs on the main thread. That’s right, the main thread. So use onStartJob() to either perform simple work, or to kick off a background service for complicated work. If you kick off another service, you’ll need to return true, but if you’re done with everything, go ahead and return false.
+onStopJob() is called by the system if the job is cancelled before being finished. Perhaps because the conditions are no longer being met, like the device has been unplugged. So use this for safety checks and clean up. And then return true if you’d like the system to reschedule the job, or false if it doesn’t matter and the job will be dropped.
+_jobFinished() is not a method you override, and the system won’t call it. That’s because you need to be the one to call this method once your service or thread has finished working on the job. This is how to system knows to release your wakelock. If you forget, your app is going to look pretty guilty in the battery stats lineup. jobFinished() takes two parameters: the current job, so that it knows which one we are talking about, and a boolean indicating whether you’d like to reschedule the job. Perhaps your work failed for some reason. This will kick off the JobScheduler’s exponential backoff logic for you (or else the logic you specified in JobInfo).
As with any service, you’ll need to add this to your AndroidManifest.xml. What’s different, though, is that you need to add a permission that will allow this service to be a JobService.
<service
android:name=".TotallyRealJobService"
android:permission=“android.permission.BIND_JOB_SERVICE" >
</service>
Finally, you schedule a job using
JobScheduler (
http://goo.gl/JPdgcO), which you can get from the system. Then, call
schedule() using that super perfect JobInfo object that you created, and you are good to go.
Not so scary, is that? There are a lot of pieces, to be sure, and you’ll need to think carefully about when and what should trigger your job. But it’s actually pretty easy to work with. And that means you can now bring it up in conversation without fearing that you’ll suddenly seem uninformed. You go, you! (But, specifically, go
#BuildBetterApps .)