Why do I get multiple active Tokens for my Device with Googles Cloud To Device Messaging Service?
Asked Answered
O

3

7

I just added C2DM capability to my Android App.

At the moment the following happens if C2DM is started in my App.

  1. My App sends the registration Intent
  2. The answer broadcast is received by my app
  3. The device token is retrieved from the intent and sent to my server

    From that moment everything is working fine. The client receives the push notifications etc. A problem occurs if the following hapens:

  4. The user uninstalls the application without disabling push. (Completely deleting it not only updating)

  5. The user reinstalls the application

If after step 5 a push notification is sent my app still receives this notification. It seems that the token which was retrieved from the previous install is still active and is reconnected to the new instance of my application.

This leeds to the following problem:

  • A user who reinstalls my app but has no intention of receiving push notifications has no possibility to remove himself from the service because the new instance of the app has no way to unregister the old token from my server.

Is this a bug in the C2DM system or is something wrong in my setup?

Update

I followed Berdons advice and did the following:

For testing purposes only start an unregister Intent every time my app starts up. After I send the unregister intent no push notification from my server is sent to my application. That seems to do the trick, but if I now go the C2DM Settings Screen and turn on push notifications for my app all the old tokens get active again and I receive information that I did not register for in the current installation of my app.

Next Update

It seems I'm not the only one with this problem:

Android C2DM : Duplicate message to the same device and App

I hoped that Google would manage those tokens in a way that old tokens from the same device get disabled after a new one was issued. I also expect that after I sent an unregister Intent all tokens for that application and that device are marked as invalid or deleted from the Google Server for ever. If this is somehow a design decision by Google for special use cases I don't see please enlighten me.

Orrery answered 8/8, 2011 at 15:33 Comment(2)
I'm in the process of trying to implement C2DM myself. My approach has been to ensure the user is registered on my app server. If they uninstall it will 'disable their account on my app server and if they re-install, they have to re-register (re-enable) their account on my app server. That way you can control when and if to push notifications to them, even if the token is valid.Superintendency
@John How do you notice that a user uninstalls your application?Orrery
O
4

We now found a solution that should work in most of the cases.

The server adds the C2DM registration id as a data field with every C2D Message.

  • The device now only shows a notification if the token in the message and the token that is stored in a pref file match. That way we guarantee that we don't show messages for device tokens that were obtained by previous installs.
  • If the tokens do not match we found an old token that should not be active anymore. We now mark the token on our own web server as inactive to prevent the server from sending more unnecessary C2D Messages

This solution enables us to show only relevant data without the need to store a unique user id.

Orrery answered 18/8, 2011 at 8:31 Comment(2)
That way we guarantee that we don't show messages for device tokens that were obtained by previous installs. But when we uninstall app, Token saved in Pref was gone away. So what is the best way to save this Token?Crowley
The token is saved in the backend. If the user reinstalls the app and activates push he gets a new token but the old token also receives pushes. I only knew the new token, through sending the old token with the push I,m able to filter all messages that are send to "wrong" tokens. I can now extract the wrong token from the message and remove it from our backend.Orrery
P
3

In my C2DM implementation, each user's device token is saved in a database against their UDID and the package name of the app (among other things). The UDID and package name form the primary key, meaning that the table can list multiple apps from the same device (UDID). When a user runs a particular app, the device token is recorded, and if they uninstall and re-run the app, the new device token would be recorded over the old one. We also have columns to record whether push is active for that particular app/device combo, and which types of push messages the user has enabled/disabled.

When the time comes to send a push for a particular app, no UDID will be registered more than once (since these two fields form the primary key), and therefore only the latest device token will be used. Furthermore, our query only returns the rows that have push messages enabled.

This solution should solve your problem because it prevents you from sending the push to both device tokens. I hope this helps!

Pelorus answered 9/8, 2011 at 10:48 Comment(3)
I think your solution is the only way to do it but I hoped to get away without having to generate something other then the device token to identify my users. How do you obtain a valid Value for UDID?Orrery
final TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); String deviceID = tm.getDeviceId(); You will need the permission READ_PHONE_STATE. Also, while researching the topic I've just learned that getDeviceId() only works for phones and will therefore not work for tablets. See #2322734Pelorus
In reply to Robert Peacock's reply to Janusz... I would suggest using Android_ID instead of getDeviceId if you can. See the Stackoverflow link below for a great routine that returns an ID the best way(s) possible. #5088974Heroworship
J
1

More like an unexpected "feature". You might consider issuing an unregister request on the "first run" (first run ever) of your application to prevent this from occuring.

Update
You could could do the work of differentiating between different C2DM messages by using the collapse_key (or anything of your own creation) as an identifier. Update it between registrations and pass it to the device following registrations, unregistrations and messages.

Job answered 8/8, 2011 at 15:38 Comment(2)
I tried that but it seems that the token is only invalid as long as I don't register a new one.Orrery
Did you do it correctly?code.google.com/android/c2dm/#unregistering Either way, after unregistering, just ignore any C2DM's that arrive if the user opted not to receive them - this handles the case where there is actually a bug with unregistering - which I haven't observed first hand btw.Job

© 2022 - 2024 — McMap. All rights reserved.