Implementing GCM Network Manager for periodic network requests on Android
In the process of rebuilding What’s Shaking, NZ?, I needed to implement a periodic network request (literally polling an API). I wanted to use the new Job Scheduler API, but unfortunately, this is only available on API 21 and above. Luckily we can get similar functionality by using GCM Network Manager, as suggested on StackOverflow. Note that the GCM Network Manager actually uses Job Scheduler behind the scenes in API 21+.
The documentation for this is somewhat hand-wavy. Here I attempt to provide a true step-by-step guide to implementing this. I assume you’re not already using GCM for something else in your app (as that was the case for me).
The first step is to import GCM in your
Now you can implement
GcmTaskService. This is as simple as the following:
1 2 3 4 5 6 7 8 9 10 11
Great. So you get a callback, on a different thread, where you can do your stuff.
Add the service to the manifest
The instructions say to add the service to the manifest and “Add all applicable intent filters. See details for intent filter support in the GcmTaskService API reference.”
Note that the GcmTaskService documentation has
SERVICE_ACTION_EXECUTE_TASK as the name for the
com.google.android.gms.gcm.ACTION_TASK_READY intent filter. This is right now the only thing we need to care about.
We also need to add the
RECEIVE_BOOT_COMPLETED permission so that our periodic sync will persist across reboots.
1 2 3 4 5 6 7 8 9 10 11 12 13
Schedule a persistent task
You construct a
PeriodicTask object using a
Builder, and then pass that task to a
GcmNetworkManager instance - and that’s it! You can put this in your
SyncService class and call
1 2 3 4 5 6 7 8 9 10 11 12
I’ve used the Once library to ensure that my periodic sync is scheduled once per app install (on first launch). I just call this method from my Application class
1 2 3 4 5 6
Re-schedule on app update
Finally, we need to ensure that our periodic task is re-scheduled after an app update by overriding the
When your package is removed or updated, all of its network tasks are cleared by the GcmNetworkManager. You can override this method to reschedule them in the case of an updated package. This is not called when your application is first installed.
This is called on your application’s main thread.
This is trivial enough to do:
1 2 3 4 5 6
You can test that your background process works by firing off the intent that triggers it:
1 2 3
speakman.whatsshakingnz is the package, and
.network.SyncService is the component name within that package. You need to specify the tag you used earlier, too. If you’ve got a debugger attached you can hit a breakpoint inside your
onRunTask method and note that you’re not on the main thread.
- you have to reschedule on app update - this is simple enough to do, make sure you remember to do it!
- check for Play Services! It’s required for this to work.
- if the network is unavailable/doesn’t meet the criteria you specified, you can’t force the task to trigger via ADB (useful to remember if you keep your test device in airplane mode!)
- use the tags to filter out different events in the same service -
taskParams.getTag()returns the tag that the task was created with.