I'm building GCM into my app and I want to make sure I don't end up with duplicate device ID's.
Is there a 'best practice' for dealing with device ID's? My original though was when the app loads it calls gcm.register, and posts the ID to my server, and if the key isnt in my database, I'll store it, then when I send out a notification, loop through the DB and send the messages.
But I as wondering if the ID ever changes, I don't want to send multiple messages to one device.
yes it is possible for the ID to change. If you take a look at the tutorial in the SDK, every time the app is updated to a new version it will go and get a new ID because the previous ID is not guaranteed to work.
specifically take a look at this page
http://developer.android.com/google/gcm/client.html
Check if app was updated; if so, it must clear the registration ID
since the existing regID is not guaranteed to work with the new
app version.
I read the 2 reasons over here when you GCM Registration Id might change:
You’ll need to re-register every device each time you update your
app.
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.
In addition to #tyczj's answer of change of ID's on updating the app, Google says that it may also automatically refresh the ID's. If you read 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.
Just an addition info that for handling this case 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.
I think it would be better if you can have login based app and id validated or update at each login. I have a similiar app and its is working for me.
Related
I'm a bit confused about how to manage registration ids for all app installations.
In the app server database I have a User table and a UserDevice table. Every User may have many UserDevices. Each UserDevice have a registration id. So when a user should be notified I send the message to all the registration id's for all the devices of the user.
But when the application is reinstalled, Android is updated or something else happens that causes the registration id to change, the app will send a new registration id to our app server. But I have no way to know if this is a new device or if an existing UserDevice should be updated with the new registration id.
How is this supposed to be handled? My first thought is to send a persistent hardware ID as well as the registration ID, but perhaps there is a better way?
You don't have to worry about this. If the user does reinstall the app and the token is refreshed just add it to the users list of tokens (keeping the old one for now).
next time you send a notification to this user it will fail on the token that is no longer used. Now all you have to do when you get the fail reply from google is remove that token from your devices table.
Remember if you fail to send to a token for reasons such as invalidRegID or NotRegistered then the GCM will/has unregistered that token so it is no good so it needs to be removed from your list otherwise you will get in googles bad books for repeatedly sending to the same failed token. So remove ones that fail.
when my apps start i always check to see if the device is registered if it is I send the same token to my app server just incase it somehow got deleted.
Hope this helps
You could take a look at GCM's Device Group feature, which is explicitly intended for the "one user, many devices" problem:
https://developers.google.com/cloud-messaging/notifications
I use PushSharp and there I can use the different event handlers that are defined to handle subscription changes or expirations. The source code is available on github https://github.com/Redth/PushSharp/blob/master/PushSharp.Android/Gcm/GcmPushChannel.cs
You can probably apply the same logic to your application.
I am developing an app using the new Google Cloud Messaging Framework. We know that once we register our app we get a registration id. But what happens when the user unistalls the app through the device for a number of times and re installs again and again (there is no new notification sent till now). Now with many installations done google might return several new registration ids and now all the ids are saved in the app database.
If there is a notification to be sent it would be sent to all the ids previously saved also. Now my problem is that i think google is sending the notification to all the previous ids(so i get multiple notifications on the same device).
I hope i made my question clear and is there a solution to this.
You can assign a unique identifier to the app on each device. If you store that identifier on the external storage of this device, it won't be removed when the app is uninstalled. Then, when the app is installed again, you can send the registration ID along with that stored unique identifier. Your server will use the identifier to locate the old registration ID and replace it with the new one.
In addition, you should check for canonical registration IDs in the response you get from GCM. Each time to get a canonical ID, you should make sure you have that ID in your DB and remove the old ID (the one you used to send the message that got the canonical registration ID in its response).
I suggest you read the section Canonical IDs of the official documentation, as canonical IDs are specifically designed to solve your problem.
Every time you will send a message to an old registration ID Google will let you know what is the current canonical ID of the device you are sending a message to. Just make sure to replace your ID by this one.
Also make sure to check the code of the official demo here.
I developed an application which used GCM technology and everything is OK.
I observed that the registration ID of the device changes after a period of time and this has caused a problem in my app because my app is dependent on the Reg ID.
So how I can get a fixed Reg ID for clients?
I read the 2 reasons over here when you GCM Registration Id might change:
You’ll need to re-register every device each time you update your
app.
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.
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.
I have multiple different deviceids in my database table pointing to same a device because google will send me different device id when a device reinstall/install. Due to which devices getting multiple notifications which is hurting me and my users very much. Is there is a way to tell google that only send one notification to single device? or is there a way to check the id is new or old before sending request? Anyone experience with this weird issue? BTW, I am using PushSharp/ASP.NET in backend.
Update: I am now relying on native device id. So, I will remove/replace the old registration ids from my database table where native device id is same.
I think you need to remove the device id from your database once you get unregistered error code.
Unregistered Device
An existing registration ID may cease to be valid in a number of scenarios, including:
If the application manually unregisters by issuing a com.google.android.c2dm.intent.UNREGISTER intent.
If the application is automatically unregistered, which can happen (but is not guaranteed) if the user uninstalls the application.
If the registration ID expires. Google might decide to refresh registration IDs.
If the application is updated but the new version does not have a broadcast receiver configured to receive com.google.android.c2dm.intent.RECEIVE intents.
For all these cases, you should remove this registration ID from the 3rd-party server and stop using it to send messages.
Happens when error code is NotRegistered.
I recommend you to handle error codes when you send a message to a device.
http://developer.android.com/google/gcm/gcm.html
Please read role of 3rd party server. You would get more details.
Does the registration id for a device - app combo ever change? There is no mention of it's consistence in the docs (that I could find).
Also, will the same registration id be assigned to a device after an un-install and reinstall of the app?
Yes it can change. From the doc
Although the com.google.android.c2dm.intent.REGISTRATION intent is typically received after a request was made by the application, Google may periodically refresh the registration ID. So the application must be prepared to handle it at any time.
No, it won't be the same.