Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In GoogleCloudMessaging API, how to handle the renewal or expiration of registration ID?

As the question says that How to find out when does the registration ID has become invalid in GoogleCloudMessaging API? I already read the answers on few questions on similar topic: Do GCM registration id's expire? and Google Coud Mesaging (GCM) and registration_id expiry, how will I know? . The issue with those question is that the answers there are for C2DMor old GCM API which used GCMRegistrar instead of GoogleCloudMessaging API. The previous two methods have been depreciated.

I'll try to break my confusion/question stepwise:

1) Under the heading Enable GCM, in the second point it says:

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.

The registration ID lasts until the Android application explicitly unregisters itself, or until Google refreshes the registration ID for your Android application. Whenever the application receives a com.google.android.c2dm.intent.REGISTRATION intent with a registration_id extra, it should save the ID for future use, pass it to the 3rd-party server to complete the registration, and keep track of whether the server completed the registration. If the server fails to complete the registration, it should try again or unregister from GCM.

2) Now, if that's the case then I should handle the intent in a BroadcastReceiver and send the register() request again to get a new registration ID. But the issue is that on the same page under heading ERROR_MAIN_THREAD, it says that: GCM methods are blocking. You should not run them in the main thread or in broadcast receivers.

3) I also understand that there are other two scenarios when the registration ID changes( as mentioned under Advanced Topics under heading Keeping the Registration State in Sync): Application update and Backup&restore. I am already handling them on opening of the app.

4) In GCMRegistrar API, inside GCMBaseIntentService, there used to be a callback onRegistered() method, which got called when the device got registered. Here I used to persist the registration ID and send to 3rd party servers.

But, now How should I handle the updation or renewal of the registration ID, persist it and send it to 3rd party server?

It might be that either I am getting confused by reading all of it or I am missing something. I would be really thankful for your help.

Update

Even on Handling registration ID changes in Google Cloud Messaging on Android thread, there is no mentioning of how to handle the periodic refreshing of ID by Google?

like image 879
Shobhit Puri Avatar asked Jun 27 '13 05:06

Shobhit Puri


1 Answers

I am giving a way as What I implemented in my application

@Override
protected void onRegistered(Context context, String registrationId) {
     Log.i(TAG, "Device registered: regId = " + registrationId);
     //displayMessage(context, getString(R.string.gcm_registered));
     //ServerUtilities.register(context, registrationId);
     //1. Store this id to application Prefs on each request of device registration
     //2. Clear this id from app prefs on each request of device un-registration  
     //3. Now add an if check for new registartion id to server, you can write a method on server side to check if this reg-id matching for this device or not (and you need an unique identification of device to be stored on server)
     //4. That method will clear that if id is matching it meanse this is existing reg-id, and if not matching this is updated reg-id.
     //5. If this is updated reg-id, update on server and update into application prefs.
}

You can do like this also

if reg_id exists_into prefrences then
    if stored_id equals_to new_reg_id then
        do nothing
    else
        say server to reg_id updated
        update prefrences with new id
    end if
else
    update this id to application prefs
    say server that your device is registered
end if

But problem arises when, user clears the application data and you will loose the current reg-id.


Update for new API example Credits goes to Eran and His Answer Handling registration ID changes in Google Cloud Messaging on Android

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;
}
like image 181
Pankaj Kumar Avatar answered Sep 24 '22 15:09

Pankaj Kumar