I created an Android application that uses GCM for Android. This application works on multiple devices.
But suddenly, it stopped working on one device where it has worked before. I have problems only on that device: it no longer receives any messages. After some debugging and adjusting my code for testing, it seems that this device keeps getting new registration ids when registering on GCM (I suppose when you register a device multiple times, you receive the same registration ID?). I removed the app several times from the device, then reinstalled the app, and different registration ids were saved to my database (whereas for the other devices, it keeps the same registration ID).
When I debug the message transfer code, I notice GCM sends the message to multiple registration ids (all stored in my database for that same device) and every message gets status OK, but no message is received by my device. I'm familiar with a canonical ID, but this canonical ID is null in every result. So I suppose this is not the problem?
This problem came suddenly. I don't know what the problem is. The application keeps working on other devices, I only have this problem on 1 device.
Can anyone help me with this problem?
First you should know that the id you get from GCM is not constant to your device and can change, so you you must not count on it as Primary key for anything.
when you get an id from GCM you need to save it (possibly in SharedPreferences) and then each time check if this id exist or not, if yes there is no need to register with GCM.
then each time you will send a message to that id it should arrived.
GCM registration ID is not the same for a single device. GCM registration ID changes and can become invalid which is why google recommends registering again when you update your app because your current ID is not guaranteed to work.
http://developer.android.com/google/gcm/adv.html#reg-state
making a call the get a registration id may or may not return you the same registration id that you had before.
Related
Thinking of a problem that I already have 20 app instances of the app installed on different devices and I have decided that I want to install another one of this app on my newly bought device. This would really be a big problem in terms of obtaining a notification key right? because the max registration id that is allowed for notificatin_key members is 20, so I should limit my app instances.
One of the solution is to uninstall a single app instance from a device and tell my online database server to delete the saved registration id similar to the registration id of the uninstalled app. In this way, I have a permission to install the app on my newly bought device by checking my registration id field in my database if its less than or not equal to maximum number registration id which 20. Let's assume that I don't have an internet connection when I am uninstalling the app on the device. How can I update my online database server and provide another space for the newly bought device.
For those who are experienced developer of this kind of android app. Please share your thoughts on how can I properly handle this kind of situations. thanks!
You need to read Interpreting an error response in details. Your server will get Unregistered Device error [error code is NotRegistered] if application has been uninstalled from device.
So if you get this error, you can remove entry for that particular device from server's database.
From documentation
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 am doing an android application which uses gcm.I came to know that when the application is uninstalled and re installed there is no guarantee to receive the same registration id again.So what I did is while logging in I take one unique Id from application server and whenever new registration id is made I am able to replace that in application server.So what my question is, I am not using the canonical id for replacing the latest registration id in gcm server.Will it cause any problem? Please help me.
Your solution is basically good, though I'm not sure whether that unique Id your server generates is associated with the device or the logged in user. If it's the former, make sure you persist it on the device's external storage, so that it doesn't get lost when the app is uninstalled. If it's the latter, I'm not sure how you are handling the case of the same user logging in on multiple devices.
While your strategy is good for maintaining the current registration ID on both the device and your server, you should still handle canonical registration ID responses from Google just to be safe.
On the server side, as long as the application is behaving well,
everything should work normally. However, if a bug in the application
triggers multiple registrations for the same device, it can be hard to
reconcile state and you might end up with duplicate messages.
GCM provides a facility called "canonical registration IDs" to easily
recover from these situations. A canonical registration ID is defined
to be the ID of the last registration requested by your application.
This is the ID that the server should use when sending messages to the
device.
If later on you try to send a message using a different registration
ID, GCM will process the request as usual, but it will include the
canonical registration ID in the registration_id field of the
response. Make sure to replace the registration ID stored in your
server with this canonical ID, as eventually the ID you're using will
stop working.
Source : http://developer.android.com/google/gcm/adv.html#canonical
I am working on an android project which uses gcm. I came to know that if we uninstall the appfrom device and reinstalled most of the time the device gets new registration id.Then if we do not delete the old one from application server and update, The messages will be sending to both ids and in the response it will be showing canonical id is present.My question is, at this point message will be successfully send to that device or not?
When you receive a canonical registration ID in the response from Google, the message was accepted by the GCM server and the GCM server would attempt to deliver it to the device. Whether it is actually sent to the device depends on whether the device is available (i.e. connected to the internet).
So if your server sends a GCM message to both the old ID and the new ID, the device will probably get two messages.
Canonical IDs
On the server side, as long as the application is behaving well,
everything should work normally. However, if a bug in the application
triggers multiple registrations for the same device, it can be hard to
reconcile state and you might end up with duplicate messages.
GCM provides a facility called "canonical registration IDs" to easily
recover from these situations. A canonical registration ID is defined
to be the ID of the last registration requested by your application.
This is the ID that the server should use when sending messages to the
device.
If later on you try to send a message using a different registration
ID, GCM will process the request as usual, but it will include the
canonical registration ID in the registration_id field of the
response. Make sure to replace the registration ID stored in your
server with this canonical ID, as eventually the ID you're using will
stop working.
(Source)
You can overcome this problem by assigning a unique identifier to each instance of your application. If you store that identifier in the device's external storage, it won't be deleted when the app is uninstalled. Then you can recover it when the app is installed again. If you send this identifier to your server along with the registration ID, you can check if your server has an old registration ID for this identifier, and delete it.
#Eran We have two option either to remove older registration ids or update with Key and position of canonical id. I prefer to update... You can view working code of mine i have answered here Steps to Update Canonical Ids
I have been working on GCM for my Android app for a bit. I have noticed that almost every time I have a different GCM Registration ID for my device. Is it safe for me to keep a UNIQUE_KEY constrain on GCM Registration ID? And delete all the IDs with the error NotRegistered and update all the IDs which are canonical_ids?
a registration ID is tied to a particular Android application running on a particular device.
(from GCM Overview)
Two different devices would always have a different registration id. Even different apps on the same device have different registration ids.
Functionally it is safe to keep a UNIQUE_KEY constraint on the Registration ID, but since the Registration ID can be long (up to 4096 bytes, though in practice it's usually much shorter), some databases may prevent you from defining an index or constraint on such a large column. You might want to use a one way hash function that would map the Registration ID to a smaller value, store that value in a smaller column and have the constraint/index on that column.
When you get NotRegistered error, you should indeed delete that registration ID from your DB (or at least mark it with a status that says it is inactive, and stop sending messages to it). But if the app will be re-installed on a device from which it was earlier uninstalled, the app may get the same registration ID when it registers again to GCM, so your server should allow registration IDs that at one point gave NotRegistered to become active again.
You should update the old registration ID when you get canonical registration ID in the response from Google.
It depends.
In some cases, I have proved that Two or more devices can have identical Registration IDs.
I have a push enabled phonegap app, that is made to run in several devices, all the same kind (brand, model, specs...). For saving time reasons, I decided to make a nandroid backup of one device and then copy that into the others. The result: many devices, the same Reg ID. Hope this helps.
I am also confused regarding this due to following region, But i am not getting same registration Id as i Creates two demo also.
1) But one region, There is Particular sender id for Particular Application and according to that sender id there is a unique Registration id
Check for the Bold Line.As according to this Registration id always different for different application{Copy this line from http://developer.android.com/google/gcm/gcm.html}
Registration ID An ID issued by the GCM servers to the Android application that allows it to receive messages. Once the Android application has the registration ID, it sends it to the 3rd-party application server, which uses it to identify each device that has registered to receive messages for a given Android application. In other words, a registration ID is tied to a particular Android application running on a particular device.
The registration id is unique, what happens sometimes, is that your application changes.
If you change the package name, or a whatever key used to be publish, debug or release key, then your registration id changes.
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.