Gcm Registration Id Changed

GCM Registration ID changed

I read the 2 reasons over here when you GCM Registration Id might change:

  1. You’ll need to re-register every device each time you update your
    app.
  2. You’ll also need to re-register a device if the version of Android it’s running has been updated

P.S: The below old answer's reference has been removed from Google's page, so might not be valid anymore

If you see 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, 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. The broadcast receiver will have the onReceive method with an Intent. From the intent you can get the Bundle using which you can extract the new registration ID from Google. You can save that and send it to the 3rd part server to replace your previous registered ID for that user.

Also you may see this answer on the question In GoogleCloudMessaging API, how to handle the renewal or expiration of registration ID?.

Discussion on Should applications call gcm.register() every seven days to ensure valid registration IDs? question might also be of some use.

Hope this helps you understand how to handle it.

What is GCM Registration ID?

A Registration ID is an identifier assigned by GCM to a single instance of a single application installed on an Android device. The device is assigned this identifier when it registers to Google Cloud Messaging. The GCM documentation doesn't specify what information is encoded in this identifier.

In some older Android versions (pre-4.0.4), a Google account is required to register to GCM.

If multiple users use the same app on the same device, they will be have the same registration ID, since GCM doesn't care about which user logs-in to the app. It's up to your server to determine which user is currently logged in to your app in a certain device, and based on that knowledge to deliver only relevant GCM messages to that device.

Updating GCM registration ID after device update

You don't have to un-register before registering again to GCM, unless you are changing the sender ID (project number) used to register. In fact, the registration ID may even stay the same if you register with the same sender ID.

Handling registration ID changes in Google Cloud Messaging on Android

That's an interesting question.

Google encourage you to switch to the new registration process :

An Android application running on a mobile device registers to receive messages by calling the GoogleCloudMessaging method register(senderID...). This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous GCM registration process.

The note that says Google may periodically refresh the registration ID only appears on the page that still shows the old registration process, so it's possible that this note is no longer relevant.

If you want to be safe, you can still use the old registration process. Or you can use the new process, but have in addition the code that handles the com.google.android.c2dm.intent.REGISTRATION intent, in order to make sure you are covered if Google do decide to refresh the registration ID.

That said, I never experienced such a refresh, and even when I did experience a change in the registration ID (usually as a result of sending a notification after un-installing the app and then re-installing it), the old registration ID still worked (resulting in a canonical registration ID sent in the response from Google), so no harm was done.

EDIT (06.06.2013) :

Google changed their Demo App to use the new interface. They refresh the registration ID by setting an expiration date on the value persisted locally by the app. When the app starts, they load their locally stored registration id. If it is "expired" (which in the demo means it was received from GCM over 7 days ago), they call gcm.register(senderID) again.

This doesn't handle the hypothetical scenario in which a registration ID is refreshed by Google for an app that hasn't been launched for a long time. In that case, the app won't be aware of the change, and neither will the 3rd party server.

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
mDisplay = (TextView) findViewById(R.id.display);

context = getApplicationContext();
regid = getRegistrationId(context);

if (regid.length() == 0) {
registerBackground();
}
gcm = GoogleCloudMessaging.getInstance(this);
}

/**
* Gets the current registration id for application on GCM service.
* <p>
* If result is empty, the registration has failed.
*
* @return registration id, or empty string if the registration is not
* complete.
*/
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.length() == 0) {
Log.v(TAG, "Registration not found.");
return "";
}
// check if app was updated; if so, it must clear registration id to
// avoid a race condition if GCM sends a message
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion || isRegistrationExpired()) {
Log.v(TAG, "App version changed or registration expired.");
return "";
}
return registrationId;
}

/**
* Checks if the registration has expired.
*
* <p>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;
}

EDIT (08.14.2013) :

Google changed their Demo App again (two days ago). This time they removed the logic that considers the Registration ID to be expired after 7 days. Now they only refresh the Registration ID when a new version of the app it installed.

EDIT (04.24.2014) :

For the sake of completeness, here are the words of Costin Manolache (taken from here), a Google developer involved in the development of GCM, on the matter :

The 'periodical' refresh never happened, and the registration refresh
is not included in the new GCM library.

The only known cause for registration ID change is the old bug of apps
getting unregistered automatically if they receive a message while
getting upgraded. Until this bug is fixed apps still need to call
register() after upgrade, and so far the registration ID may change in
this case. Calling unregister() explicitly usually changes the
registration ID too.

The suggestion/workaround is to generate your own random identifier,
saved as a shared preference for example. On each app upgrade you can
upload the identifier and the potentially new registration ID. This
may also help tracking and debugging the upgrade and registration
changes on server side.

This explains the current implementation of the official GCM Demo application.
com.google.android.c2dm.intent.REGISTRATION should never be handled when using the GoogleCloudMessaging class to register.

Keeping app GCM registration ID valid robustly during automatic updates

What about below solution:

Create a BroadcastReceiver for intent ACTION_PACKAGE_REPLACED. You will receive this intent when a new version of the package gets installed. Once you get this intent you can re-register to GCM for new registration Id.

Broadcast Action: A new version of an application package has been installed, replacing an existing version that was previously installed. The data contains the name of the package.

Do GCM registration id's expire?

EDIT: THIS ANSWER IS WAY OUT OF DATE, I HAVE NO IDEA WHAT THE CURRENT BEHAVIOR IS


I found the answer myself. You don't explicitly need to re-register all the time, just once according to the example in the docs.

Also, unlike previous versions of GCM and C2DM, Google itself does not refresh the registration itself now: once you have the registration id from the initial registration you are good to go, except for one case: you do still need to re-register when the user upgrades to a new version (this case is also handled in the example in the link above):

When an application is updated, it should invalidate its existing
registration ID, as it is not guaranteed to work with the new version.
Because there is no lifecycle method called when the application is
updated, the best way to achieve this validation is by storing the
current application version when a registration ID is stored.



Related Topics



Leave a reply



Submit