1

The client-side code in the GCM example on the Android dev site defaults to calling gcm.register(SENDER_ID); after every seven days by checking if registration has expired using the following function:

public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7;

/**
 * Checks if the registration has expired.
 *
 * To avoid the scenario where the device sends the registration to the
 * server but the server loses it, the app developer may choose to re-register
 * after REGISTRATION_EXPIRY_TIME_MS.
 *
 * @return true if the registration has expired.
 */
private boolean isRegistrationExpired() {
    final SharedPreferences prefs = getGCMPreferences(context);
    // checks if the information is not stale
    long expirationTime =
            prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
    return System.currentTimeMillis() > expirationTime;
}

The comment above the function implies that this is used to "avoid the scenario where the device sends the registration to the server but the server loses it. Is this suggesting that our servers (not the GCM servers) may lose the registration id? Or is this because the registration ID could become invalid on the GCM side of things? It appears that this is possible as per the following paragraph in the GCM Advanced Topics Page:

Similarly, you should not save the registration ID when an application is backed up. This is because the registration ID could become invalid by the time the application is restored, which would put the application in an invalid state (that is, the application thinks it is registered, but the server and CM do not store that registration ID anymore—thus the application will not get more messages).

Thank you in advance!

Daniel Smith
  • 8,561
  • 3
  • 35
  • 58

2 Answers2

4
  1. You said:

    The comment above the function implies that this is used to "avoid the scenario where the device sends the registration to the server but the server loses it. Is this suggesting that our servers (not the GCM servers) may lose the registration id? Or is this because the registration ID could become invalid on the GCM side of things?

    I think they are talking about our servers( the 3rd party servers) and NOT GCM servers. The second point will clear that a bit more.

  2. Also, you mentioned that the docs say:

    You should not save the registration ID when an application is backed up. This is because the registration ID could become invalid by the time the application is restored, which would put the application in an invalid state.

    I think If you carefully read the second point under the heading Enable GCM on Architectural Overview page, it says:

    Note that Google may periodically refresh the registration ID, so you should design your Android application with the understanding that the com.google.android.c2dm.intent.REGISTRATION intent may be called multiple times. Your Android application needs to be able to respond accordingly.

    So, Google may refresh he registration ID's periodically. That's why registration ID could become invalid by the time the application is restored.

    So, for handling that you should have a Broadcast Listener which could handle com.google.android.c2dm.intent.REGISTRATION intent, which Google send to the app when it has to refresh the registration ID.

    This also might clear the first point. As this case is handling the refreshing of the ID from Google side, the local 7 days validity will handle the other case of loosing the ID on 3rd part server( as it is being refreshed periodically after every 7 days).

This is my view about your question. Hope this helps.

Sufian
  • 6,405
  • 16
  • 66
  • 120
Shobhit Puri
  • 25,769
  • 11
  • 95
  • 124
  • OK. This is very clear. That Architectural Overview paragraph is really informative. It looks like if I have a receiver in my manifest that filters for `com.google.android.c2dm.intent.RECEIVE` and `com.google.android.c2dm.intent.REGISTRATION` events, I can just handle the differences in the receiver's `onReceive` method by checking for "registration_id" as a string extra in the intent as per [the advanced info document](http://developer.android.com/google/gcm/adv.html#reg-state) and then saving the new ID given by google on a periodic ID refresh. – Daniel Smith Jul 27 '13 at 00:00
  • You are right that in old way, you can directly handle the case of refreshing of the ID inside `onReceive` method. Although `onReceive` way of doing Push has been depreciated. The new way suggests to just have broadcast listener for that. Also, In this new way, the call to `gcm.register()` (registering the push) is a blocking method, unlike previous way of doing the push registration where it the app used to receive a callback inside `onRegistered` method. – Shobhit Puri Jul 27 '13 at 00:04
  • I meant the `onReceive` method of the BroadcastReceiver http://developer.android.com/reference/android/content/BroadcastReceiver.html – Daniel Smith Jul 27 '13 at 00:07
  • 1
    Regarding the update: you shouldn't need to call `gcm.register()` when the `BroadcastReceiver` receives an event. Even if that event is a register event, GCM is sending you the new registration ID, so the client's responsibility is to send this new ID to the 3rd party server and to save it to shared prefs, not to re-register with GCM (as this has already happened--the app's receiver wouldn't receive a message if this hadn't yet happened). – Daniel Smith Jul 27 '13 at 00:23
  • On you're right. Foolish me! I forgot that it has an `Intent` associated with `onReceive` method. I'll update the answer accordingly. Thanks for the correction :) – Shobhit Puri Jul 27 '13 at 00:25
3

To clarify the 'backup/restore' case: the registration ID is tied to a specific device. If the app is restored on a different device - the previous registration ID still points to the old device, the only way to get messages on the restored device is to get a new registration ID.