Neither old or new registration id is canonical
This was a bug in gcm which is now fixed.
Now if I send notification to old gcm id, it returns the new registration id as canoncial id.
Source: https://github.com/google/gcm/issues/94
Android using Canonical ID GCM
Yes. You can use canonical IDs to help you more easily recover from your errors. It is the registration token of the last registration requested by the client app. This is the ID that the server should use when sending messages to the device.
If you try to send a message using an old registration token, GCM will process the request as usual, but it will include the canonical ID in the
registration_id field
of the response. Make sure to replace the registration token stored in your server with this canonical ID, as eventually the old registration token will stop working.
Based from this blog, GCM service returns the cannonical IDs in the order notifications were sent. Here is a sample response:
{
"multicast_id": 7036866281258904189,
"success": 1,
"failure": 0,
"canonical_ids": 1,
"results": [
{
"registration_id": "CANNONICAL_REGISTRATION_ID",
"message_id": "0:1415529915241995%64ac3713f9fd7ecd"
}
]
}
The canonical id = 0 means that registration id which your push sever used is OK and not should be replaced by canonical id, i.e. often GCM server will be response canonical_id = 0.
In the example response there's one cannonical id and it means that your server has to replace existing registrtation id on new value which you see in response. This case easy reproduce if user reinstall your client application, but your push server doesn't know about it and GCM server will pass in response new registration id.
Check these related SO questions about Canonical IDs:
- How to get Canonical ID from GCM
- Get GCM canonical registration ID without sending a message
Get GCM canonical registration ID without sending a message
You can specify "dry_run": true
option in /send
request.
I found that devices do not receive any push notifications with "dry_run": true
option, while a server get canonical_ids
response.
Here is a sample code in Ruby. You may have to install gcm
Gem beforehand.
$ gem install gcm
ask_canonical_ids.rb
require 'gcm'
require 'json'
API_KEY = "YourApiKey"
gcm = GCM.new(API_KEY)
registration_ids = [
'OldRegistrationId',
]
option = { data: { 'message' => 'Hello Gcm!' }, dry_run: true }
response = gcm.send_notification(registration_ids, option)
p response[:canonical_ids]
output of $ ruby ask_canonical_ids.rb
(formatted)
[{
:old => "OldRegistrationId",
:new => "NewRegistrationId"
}]
Again, your device will not receive any push notifications.
CM getting Canonical ID
Here's an example of how the response is parsed by Sender.java in sendNoRetry
method :
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream()));
try {
String line = reader.readLine();
if (line == null || line.equals("")) {
throw new IOException("Received empty response from GCM service.");
}
String[] responseParts = split(line);
String token = responseParts[0];
String value = responseParts[1];
if (token.equals(TOKEN_MESSAGE_ID)) {
Builder builder = new Result.Builder().messageId(value);
// check for canonical registration id
line = reader.readLine();
if (line != null) {
responseParts = split(line);
token = responseParts[0];
value = responseParts[1];
if (token.equals(TOKEN_CANONICAL_REG_ID)) {
builder.canonicalRegistrationId(value);
} else {
logger.warning("Received invalid second line from GCM: " + line);
}
}
Result result = builder.build();
if (logger.isLoggable(Level.FINE)) {
logger.fine("Message created succesfully (" + result + ")");
}
return result;
} else if (token.equals(TOKEN_ERROR)) {
return new Result.Builder().errorCode(value).build();
} else {
throw new IOException("Received invalid response from GCM: " + line);
}
} finally {
reader.close();
}
} finally {
conn.disconnect();
}
As you can see, the canonical registration ID is searched for in the second line of the response, but only if the first line of the response contains message ID.
android GCM get original id of canonical id
As described in the post that you linked to, it's all based on the position in the response list. So when you get the canonical ID you need to update the original registration ID in the same position of your "send list".
So in your example here are the results 4 of which are canonical (0, 3, 4, 5):
[0] {"registration_id":"3","message_id":"m1"},
[1] {"message_id":"m1"},
[2] {"message_id":"m1"},
[3] {"registration_id":"3","message_id":"m1"},
[4] {"registration_id":"3","message_id":"m1"},
[5] {"registration_id":"3","message_id":"m1"}
And here is your "send list":
[0] "1",
[1] "2",
[2] "3",
[3] "4",
[4] "5",
[5] "6"
According to the results you need to update the registration ID's in position 0, 3, 4, 5 to the ID of 3. That means that you will end up with a registration list like the following:
[0] "3",
[1] "2",
[2] "3",
[3] "3",
[4] "3",
[5] "3"
And finally:
[0] "3",
[1] "2",
Also see: https://developer.android.com/google/gcm/adv.html#canonical and https://developer.android.com/google/gcm/gcm.html#response
Reproduce canonical Id as 1 in send notification using GCM
Steps to produce Canonical error while sending notification using GCM
The initial state : Application is installed on Android device and is registered to GCM. Sender server has the registration Id and manages to send messages to that device.
Uninstall the application.
Send two messages to the original (old) registration Id. The first will seem to work (server will receive a successful reply from GCM server). The second attempt will result in a "NotRegistered" error.
Re-install the application and register to GCM. The device will get a new registration Id.
Send a message using the old registration Id. The application will receive the message, but the server will get in the reply the new registration Id as canonical registration Id.
Source : https://stackoverflow.com/a/12978274/2189626
Related Topics
Android Material Chip Component Crashing App. Unable to Inflate Xml
Disable Home Button in Android Ics (4.0)
Getlaunchintentforpackage Is Null for Some Apps
How to Find the Android Version Name Programmatically
Android: Showing Wrong Screen Resolution
Handling Keepsynced() While on Background on Android and with Fcm
Error Building Player: Commandinvokationfailure: Unable to Convert Classes into Dex Format
Differencebetween the States Selected, Checked and Activated in Android
Debugging with Android Studio Stuck at "Waiting for Debugger" Forever
How to Have a Listview/Recyclerview Inside a Parent Recyclerview
Android - What Is the Meaning of Stableids
Opencv Android Green Color Detection
Garbage Collection Causes:Mediaplayer Finalized Without Being Released
Android - Margins Specified in Custom Style Not Taking Effect
How to Change Images on Imageview After Some Interval
How to Calculate Phone's Movement in the Vertical Direction from Rest
How to Fill Recyclerview with Gridlayoutmanager from Right to Left
How to Get a Fragment to Remove Itself, I.E. Its Equivalent of Finish()