Question

I'm using a SyncAdapter and GCM to notify my app of different types of changes on the backend server. For example, if change A happens on the server, I do a push notification with a field called change_a that I pass to the SyncAdapter through ContentResolver.requestSync(). This way, the SyncAdapter knows what to sync from the server. Similarly, for a change B, I send a field called change_b.

This works perfectly except for one use case. I send a change_a notification, it calls ContentResolver.requestSync() but, because there is no network availability, the SyncAdapter is not yet called. If after that, I send a change_b notification, again ContentResolver.requestSync() is called with the new field. And then, when the networks is up, the SyncAdapter is called but only with the latest field change_b and accordingly, it won't sync the change A.

So, basically, ContentResolver.requestSync() overrides all previous requestSync() calls that haven't yet triggered the SyncAdapter. The SyncAdapter runs with the latest extras that were sent.

One solution to this is to not differentiate between a change A and a change B and have the SyncAdapter sync everything. But this is costly for the bandwidth. I want to control what and when to sync. Is there something I could do to fix this (a syncadapter flag maybe)?

Was it helpful?

Solution

It seems I drew the wrong conclusions. Actually, after some further testing, if requestSync() is called with different extras, SyncAdapter is called several times, for each different Bundle.

My problem was somewhere else. When I would receive a push notification, I would schedule an alarm to trigger the sync request and I would use a PendingIntent with the flag PendingIntent.FLAG_CANCEL_CURRENT, which meant that if another push notification came before the alarm went off, the alarm would be overwritten with the new data. And so, if the device was offline, when it came online, it received all the pending push notifications and there would be only one alarm set with the data from the most recent push notification.

The way I solved this problem, is by setting a different action on each PendingIntent so that setting a new alarm of the same type doesn't overwrite the other types of alarms.

And a improvement to this would be to add a collapse_key for each type of sync so that only one of each kind of push notification gets delivered to the device.

OTHER TIPS

It seems I drew the wrong conclusions. Actually, after some further testing, if requestSync() is called with different extras, SyncAdapter is called several times, for each different Bundle.

If you use different extras in multiple calls to requestSync(), then performSync() will be called for each requestSync(). I want to add proof: the toKey() call inside SyncOperation.java incorporates values from inside the extras Bundle. This prevents SyncManager from deduping these SyncOperations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top