androidtokengoogle-cloud-messaginginstanceid

When do GCM Tokens Expire and What is the InstanceID?


Since GCM keeps getting updated, most of the resources I have searched seem outdated or unclear. Basically, I am confused over when the tokens and ID's expire. (For reference, I am working with Android.)

From what I understand (and please correct me if I'm wrong), my server has an API Key and a Sender ID. Using the Sender ID I can have my client request a Token via the InstanceID stored locally on my client. I'm already a bit confused here. The InstanceID is assigned the moment my app goes online? Does it ever change? What about when the app upgrades or is uninstalled and reinstalled (or the device is restored)? By calling InstanceID.getInstance will I always retrieve the same InstanceID, or will it eventually expire and give me a new one? Is there any value to storing the string you retrieve by calling getID()? The docs seem to indicate that you actually retrieve a new InstanceID when you call getID(), so that complicates things even more. (For reference, I'm referring to: https://developers.google.com/instance-id/)

Using the InstanceID, my client can request a Token from the GCM servers, which it then sends to my app server. My app server stores this Token, and can use this to send messages to the GCM servers, which will then send the message to the device. The device uses the stored InstanceID to actually receive these messages, I believe. So having a class that extends GcmListenerService will allow me to receive these messages with onMessageReceived? I don't have to do anything special (other than defining it in the AndroidManifest)? I don't have to actually tell it to use the InstanceID? It just magically knows?

When do these ID's and Tokens expire? Do they expire? I store the Token as a string on the server, but if at any point one of these expires, how do I know they have expired? I can always generate a new InstanceID and Token, that much seems easy, but then do the old ones stay active? How do I wipe the old tokens from the server? There seems to be an easy way to do this with APNS on the iOS side of things, where you can retrieve a list of all the expired tokens and just wipe them from your database.


Solution

  • I've found myself asking most of these questions myself as I update my GCM implementation. After messing around with it a few days, here's my take on your questions.

    From what I understand (and please correct me if I'm wrong), my server has an API Key and a Sender ID. Using the Sender ID I can have my client request a Token via the InstanceID stored locally on my client.

    This is correct.

    The InstanceID is assigned the moment my app goes online?

    It looks like it's assigned as soon as your app launches, even if the device can't access the Internet.

    Does it ever change? What about when the app upgrades or is uninstalled and reinstalled (or the device is restored)? By calling InstanceID.getInstance will I always retrieve the same InstanceID, or will it eventually expire and give me a new one?

    According to the InstanceID documentation:

    Instance ID is stable but may become invalid, if:

    • App deletes Instance ID
    • Device is factory reset
    • User uninstalls the app
    • User clears app data

    If Instance ID has become invalid, the app can call getId() to request a new Instance ID.

    I've tested uninstalling the app and clearing the data, and the results point to all of the above being true.

    Is there any value to storing the string you retrieve by calling getID()?

    It looks like the API handles storing this in your app's local storage for you.

    Using the InstanceID, my client can request a Token from the GCM servers, which it then sends to my app server. My app server stores this Token, and can use this to send messages to the GCM servers, which will then send the message to the device. The device uses the stored InstanceID to actually receive these messages, I believe. So having a class that extends GcmListenerService will allow me to receive these messages with onMessageReceived? I don't have to do anything special (other than defining it in the AndroidManifest)? I don't have to actually tell it to use the InstanceID? It just magically knows?

    As far as I can tell there wasn't any sort of InstanceId in the previous implementation, and it doesn't look like it's being explicitly used in this one either. If it is, it's being called within either GcmReceiver or GcmListenerService.

    When do these ID's and Tokens expire? Do they expire?

    I've already addressed ID's expiring and we can find out about Tokens expiring in the Android InstanceID implementation guide:

    The Instance ID service initiates callbacks periodically (for example, every 6 months), requesting that your app refreshes its tokens. It may also initiate callbacks when:

    • There are security issues; for example, SSL or platform issues.
    • Device information is no longer valid; for example, backup and restore.
    • The Instance ID service is otherwise affected.

    The guide says to subclass InstanceIDListenerService and override onTokenRefresh() to handle these scenarios.

    I store the Token as a string on the server, but if at any point one of these expires, how do I know they have expired?

    The guide for implementing GCM on your server says that the GCM server will respond to your server with some information about the token you used to try to send the push notification.

    I can always generate a new InstanceID and Token, that much seems easy, but then do the old ones stay active?

    My tests suggest that yes, they do.

    How do I wipe the old tokens from the server? There seems to be an easy way to do this with APNS on the iOS side of things, where you can retrieve a list of all the expired tokens and just wipe them from your database.

    I'm still looking into this and will update if I can figure something out.