2

Question

What should I use in place of PeriodicTask and OneOffTask when migrating from GCM to FCM? Is there any equivalent in FCM packages?

Background

Recently Google has deprecated GCM and they provided migration guide, but I couldn't find any informations there about migrating PeriodicTasks and OneOffTasks.

The tutorial says to replace play-services-gcm with firebase-messaging but I couldn't find anything similar to the tasks inside this package, so I wonder if they completely resigned from them or if actually we can keep on using PeriodicTask/OneOffTasks?

Michał Pawlik
  • 756
  • 1
  • 9
  • 17

1 Answers1

3

The PeriodicTask and OneoffTask classes (part of the GcmNetworkManager component) can be replaced with the Firebase Job Dispatcher, which is an open source library for scheduling units of work that will be executed in your app's process. The service-side API it exposes mirrors the framework's JobScheduler API, which is slightly different from the GcmNetworkManager. Upgrading should be a fairly easy, mechanical change.

Upgrade steps

Add the following to your build.gradle's dependencies section:

implementation 'com.firebase:firebase-jobdispatcher:0.8.5'

Make your GcmTaskService implementations extend JobService instead. From this:

public class MyTaskService extends GcmTaskService {
  @Override
  public int onRunTask(TaskParams params) {
    // Runs in its own thread
    // ...
    return RESULT_SUCCESS;
  }
}

To this:

public class MyJobService extends JobService {
  @Override
  public boolean onStartJob(JobParameters job) {
    // Runs on the main thread!
    // ...
    return false; // "Did we start any background work?"
  }

  @Override
  public boolean onStopJob(JobParameters job) {
    // Runs on the main thread!
    // ...
    return false; // "Should this job be retried?"
  }
}

If you don't want to manage your own threading, you can take advantage of the SimpleJobService that comes with the library:

public class MyJobService extends SimpleJobService {
  @Override
  public int onRunJob(JobParameters job) {
    // Runs on its own thread!
    // ...
    return JobService.RESULT_SUCCESS;
  }
}

Make sure you adjust your manifest. Replace your previous GcmTaskService entry with something like this:

<service
    android:exported="false"
    android:name=".MyJobService">
    <intent-filter>
        <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
    </intent-filter>
</service>

Scheduling is simple:

// Create a new dispatcher using the Google Play driver.
FirebaseJobDispatcher dispatcher =
  new FirebaseJobDispatcher(new GooglePlayDriver(context));

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job (only runs once unless a retry is requested)
    .setRecurring(false)
    // don't persist past a device reboot (requires RECEIVE_BOOT_COMPLETE)
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
    // constraints that need to be satisfied for the job to run
    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(myExtrasBundle)
    .build();

dispatcher.mustSchedule(myJob);

Check the repo for more information.

ciarand
  • 78
  • 1
  • 7
  • Thanks for the detailed answer. I noticed this library uses some constants with GCM in name eg. `com.google.android.gms.gcm.ACTION_SCHEDULE`, shouldn't we be concerned about that? – Michał Pawlik Apr 18 '18 at 19:52
  • Since Google announced yesterday [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager), which uses Firebase JobDispatcher I take it as answer to my comment is "No" and thus JobDispatcher can be used. In fact, we should now probably consider using WorkManager instead of it. – Michał Pawlik May 09 '18 at 10:38