18

With the latest GCM update (3.0) is it still necessary to handle refreshing the registration token during situations such as reboot? This article discusses making GCM reliable and covers several conditions where the registration token can change. Are these steps necessary under the latest version? During the IO 2015 talk they talked as if the registration token was good until the app is uninstalled from the device.

InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Patrick Jackson
  • 18,766
  • 22
  • 81
  • 141
  • That OS update/reboot advice is just wrong, as stated by `hackbod` in the comments (that's Dianne Hackborn, Android Framework Engineer) – beetstra Jun 03 '15 at 14:25
  • So.. The only thing we need to implement now is that `onTokenRefresh()` method (& `Service`). Right? And the server should update the gcm from time to time, which will call that callback. Right? :) – guy_m Oct 25 '15 at 11:44

2 Answers2

19

The registration token shouldn't refresh after reboots, but there are other situations when it might get refreshed, so you need to handle it.

With the updated API you need to implement an InstanceIDListenerService in order to handle token refreshes as exemplified in the google-services#android#gcm sample app

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. This call is initiated by the
     * InstanceID provider.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }

Regarding the other situations when the token refresh might happen.

An existing registration token may cease to be valid in a number of scenarios, including:
- If the client app unregisters with GCM.
- If the client app is automatically unregistered, which can happen if the user uninstalls the application. For example, on iOS, if the APNS Feedback Service reported the APNS token as invalid.
- If the registration token expires (for example, Google might decide to refresh registration tokens, or the APNS token has expired for iOS devices).
- If the client app is updated but the new version is not configured to receive messages.

For all these cases, remove this registration token from the app server and stop using it to send messages.

To protect the client app and app server from potential malicious re-use of registration tokens, you should periodically initiate token refresh from the server. When GCM registration token refresh is initiated from server side, the client app must handle a tokenRefreshed message with the GCM registration client/server handshake
See the API reference for more information on identity and token refresh procedure.

Community
  • 1
  • 1
Alex Bitek
  • 6,529
  • 5
  • 47
  • 77
  • How to initiate token refresh from the server? There is a doc link? – CzBiX Jun 26 '15 at 02:41
  • @CzBiX Yes, the usual way you use to send a notification. Just in this case, you send a notification with some flag/content that you handle inside the app, and based on that you tell the InstanceID to unregister the previous token and get back a new one, which you send back to the server. – Alex Bitek Jun 26 '15 at 04:20
  • 2
    Thanks! But in the [doc](https://developers.google.com/cloud-messaging/registration#unregistration-and-unsubscription) of GCM, it's not recommend to unregistration. There is another better way? – CzBiX Jun 26 '15 at 07:20
  • @CzBiX No. That's the best way. – Alex Bitek Jul 14 '15 at 11:33
2

EDIT: Check out the InstanceID docs as this shows how to handle token refreshing. https://developers.google.com/instance-id/ and https://developers.google.com/instance-id/guides/android-implementation

Its not very clear from a server PoV imho.

From https://developers.google.com/cloud-messaging/registration#keeping-the-registration-state-in-sync we have

To protect the client app and app server from potential malicious re-use of registration tokens, you should periodically initiate token refresh from the server. When GCM registration token refresh is initiated from server side, the client app must handle a tokenRefreshed message with the GCM registration client/server handshake. See the API reference for more information on identity and token refresh procedure.

Hmm, no link there for API reference - so looking at the server api here https://developers.google.com/cloud-messaging/server-ref#interpret-downstream we have a canonical_ids field which is

Number of results that contain a canonical registration token. See the registration overview for more discussion of this topic.

and a results field which has

Optional string specifying the canonical registration token for the client app that the message was processed and sent to. Sender should use this value as the registration token for future requests. Otherwise, the messages might be rejected.

For client side we have the new https://developers.google.com/android/reference/com/google/android/gms/iid/InstanceIDListenerService.html#onTokenRefresh()

Called when the system determines that the tokens need to be refreshed. The application should call getToken() and send the tokens to all application servers. This will not be called very frequently, it is needed for key rotation and to handle special cases. The system will throttle the refresh event across all devices to avoid overloading application servers with token updates.

So how you initiate token refresh from the server is beyond me! But in answer to your question - yes you do still need to handle token refresh client side!

EDIT: interesting read Handling registration ID changes in Google Cloud Messaging on Android

Community
  • 1
  • 1
Dori
  • 18,283
  • 17
  • 74
  • 116