JobScheduler is the Unavoidable Better Future

627ce26ea490d993a49d6b263768ca67?s=47 Eric Cochran
September 29, 2016

JobScheduler is the Unavoidable Better Future

https://youtu.be/eNRTDkwPbx4
Persistent job scheduling implementations are going in nearly all our apps. On Android, we have AlarmManager and JobScheduler APIs. With Google Play Services, we also have GCM Network Manager and the upcoming Firebase JobDispatcher libraries. We will briefly discuss AlarmManager and its limitations as well as JobScheduler and its niceties, for those new to the API. GCM Network Manager and its usecases will be the core of this talk, and then we will cover the current abstractions that Firebase JobDispatcher gives us. GCM Network Manager is going to be unavoidable in the near future of Android development. Statically registered implicit BroadcastReceivers are going to be no-oped in coming releases. (The NEW_PICTURE action already is no-oped in 7.0.) At IFTTT, we rely on a lot of these broadcasts to run Triggers reliably, and we are now planning for the future with GCM Network Manager to continue delivering consistently great experiences for our users. The removal of these implicit broadcasts is a great push to update to persistent job scheduling!

627ce26ea490d993a49d6b263768ca67?s=128

Eric Cochran

September 29, 2016
Tweet

Transcript

  1. JobScheduler is the Unavoidable Better Future Eric Cochran Droidcon NYC

    September 29, 2016
  2. Credit @volumedownpower

  3. 3 Some explanatory text to introduce the theme of the

    deck and such. AlarmManager AlarmManager manager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
 Intent intent = new Intent(context, SyncJobService.class);
 manager.setInexactRepeating(ELAPSED_REALTIME,
 SystemClock.elapsedRealtime() + INTERVAL_MILLIS, INTERVAL_MILLIS,
 PendingIntent.getService(context, REQUEST_CODE, intent, FLAG_CANCEL_CURRENT));
  4. 4 Some explanatory text to introduce the theme of the

    deck and such. AlarmManager public final class RescheduleAlarmsReceiver extends BroadcastReceiver {
 @Override public void onReceive(Context context, Intent intent) {
 // Reschedule.
 }
 } <receiver android:name=".RescheduleAlarmsReceiver">
 <intent-filter>
 <action android:name="android.intent.action.BOOT_COMPLETED"/>
 </intent-filter>
 </receiver>
  5. 5 AlarmManager Persistence? Failures and retries?

  6. 6 Some explanatory text to introduce the theme of the

    deck and such. Broadcasts android.net.conn.CONNECTIVITY_CHANGE android.hardware.action.NEW_PICTURE android.hardware.action.NEW_VIDEO and more…
  7. 7 Context-aware Reduce complexity JobScheduler

  8. 8 JobInfo.Builder exponential backoff persisted across reboots maximum delay charging

    network type device idle Creating a Job
  9. 9 JobInfo.Builder addTriggerContentUri (android.hardware.action.NEW_PICTURE) Creating a Job

  10. 10 JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
 ComponentName jobService = new

    ComponentName(context, SyncJobService.class);
 JobInfo job = new JobInfo.Builder(jobId, jobService)
 /*
 More options here.
 */
 .build();
 scheduler.schedule(job); JobScheduler
  11. 11 public final class SyncJobService extends JobService {
 @Override public

    boolean onStartJob(final JobParameters params) {
 // Wakelock held.
 // Run on main thread.
 final AtomicBoolean moreWorkToBeDone = new AtomicBoolean(true);
 work.enqueue(new Callback() {
 @Override result(boolean success) {
 moreWorkToBeDone.set(false);
 boolean needsReschedule = !success; // Wakelock released.
 jobFinished(params, needsReschedule);
 }
 });
 return moreWorkToBeDone.get();
 }
 
 @Override public boolean onStopJob(JobParameters params) {
 // Wakelock released.
 boolean reschedule = true;
 return reschedule;
 }
 } JobScheduler
  12. 12 <service android:name=".SyncJobService"
 android:permission="android.permission.BIND_JOB_SERVICE"/> JobScheduler

  13. 13 For more than Lollipop GcmNetworkManager

  14. 14 new PeriodicTask.Builder()
 .setService(SyncTaskService.class)
 .setTag(jobId)
 .setUpdateCurrent(true) // Override existing task

    with equal tag.
 .setPersisted(true) // Requires permission, of course.
 .setRequiredNetwork(NETWORK_STATE_UNMETERED)
 .setRequiresCharging(true)
 .setPeriod(INTERVAL_SECONDS) // Required. In seconds.
 .build(); GcmNetworkManager
  15. 15 new OneoffTask.Builder()
 .setService(SyncTaskService.class)
 .setTag(jobId)
 .setExecutionWindow(0, 60); // Required. In

    seconds. .build(); GcmNetworkManager
  16. 16 <service android:name=".SyncTaskService"
 android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
 <intent-filter>
 <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
 </intent-filter>
 </service> GcmNetworkManager

  17. 17 public final class SyncTaskService extends GcmTaskService {
 @Override public

    int onRunTask(TaskParams taskParams) {
 // Wake lock held for about three minutes.
 // Run on background thread. Must be thread-safe.
 boolean success = work.execute();
 if (success) {
 return RESULT_SUCCESS;
 }
 return useBackoffReschedule ? RESULT_RESCHEDULE : RESULT_FAILURE;
 }
 
 @Override public void onInitializeTasks() {
 // Run on main thread after GPS or app update.
 // Reschedule all Tasks.
 }
 } GcmNetworkManager
  18. 18 What about Firebase JobDispatcher? Pluggable Drivers to wrap GCM,

    JobScheduler, AlarmManager, etc. But, almost certainly abandoned without a DEPRECATED label.
  19. 19 JS JobScheduler vs GCM Network Manager GCM API 21+

    Configurable initial backoff and linear or exponential backoff Persistent More configurable and suitable for wide range of usecases Devices with Google Play Services Exponential backoff Requires persistent backing data to reschedule after update Targeted at quick network requests
  20. 20 Great Abstraction for Tasks. Not a Perfect Transition from

    Broadcasts.
  21. 21 @Eric_Cochran github.com/NightlyNexus nightlynexus.com