I have a problem with understanding Canonical Registration Id and getting it returned by Google. I have deliberately registered my Android app twice (to test Canonical Registration Id) but when I try to push a message to both Registration Ids I don't get in the return from Google a Canonical Registration Id.
In addition, I would like to know what the format of the message Id returned by Google means. I can see in the log that it seems to consist of three parts <something>:<something2>%<something3>. Any idea what they mean? Does the 3rd part identify the device?
[INFO com.bipper.filters.PushUpdatesFilter] [ messageId=0:1349819220154718%921c249a6e2555b5 ]
[INFO com.bipper.filters.PushUpdatesFilter] [ messageId=0:1349819220242456%921c249a6e2555b5 ]
I managed to get a canonical registration id from GCM this way :
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.
Related
I am using GCM for triggering notification to my android app. notification are triggered from my server. for example suppose the user registers an account in app then server will be sending notifications for that I am passing GCM registration id in my registration request. till now it works perfectly. now I have one more API that is another server. and I am sending the same GCM Registration Id in that request, but I am not getting any notification from that server, so from some reading I have found that each registration_id is associated with a particular app and its corresponding server API key i.e. a single device has different registration_ids for different apps Thus, we got a MismatchSenderId error while trying to send push notifications using the registration_id. how do I resolve this ? I have googled and didn't find any proper solution.
I am generating GCM registration in this way :
String token = instanceID.getToken(defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Since you have 2 different servers, I believe you have two different sender ID. So in your code, you must have 2 token, one for each server.
Sample:
Token for server 1:
String token = instanceID.getToken(<sender_id_1>),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Token for server 2:
String token2 = instanceID.getToken(<sender_id_2>),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
There can be an issue in case when a token is updated:
in InstanceIDListenerService I see no way to identify token was updated - for sender_1 or for sender_2.
So it seems when onTokenRefresh is called we have to get new tokens for both senders.
I have a problem with an app using GCM, the scenario is this:
the app is installed
the app calls the GCM register method getting the registration id "RID-1"
the app is uninstalled
the app is installed again
the app calls the GCM register method again getting the registration id "RID-2"
In step 5, I need to get the previous registration id so I can update my model.
Limitations:
- I am trying to do this without using the external storage
- I can't update the model when the server sends a message, it should be done after the registration because a new profile is created in the app for each new device
I know that this information is in Google servers because it is sent to you when you send a message to the old registration id. For example, if I send a message to "RID-1", in the response I get that the new (canonical) registration id is "RID-2". What I need is a way to get this information without sending a message.
Let me know if you need more context.
I found several related questions but the answers doesn't apply to this scenario:
Registration ID duplication for GCM
gcm canonical id should be updated or not
Persistance of gcm registration id
Google Cloud Messaging - Registration ID status
Android GCM: How to detect registered canonical ids in my own server?
Handling registration ID changes in Google Cloud Messaging on Android
(all answered by #eran)
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.
We need to update registration id with Canonical Id( By finding index position of array). You may Follow this working Ready use Code
If all you need is that the user should not get a notification, send a message with parameters that your application is not looking for. You will get the canonical and your app will discard the notification if it does not have the mandatory text and message.
For example, my Cordova application plugin requires the key 'message' in the data received from the server. Otherwise it does not create a notification.
I know this is sort of a hack, but I think given the limitations, this will be the easiest to achieve.
I am experiencing a problem with getting duplicate notifications using GCM push notifications on the Android client side.
I install the app and register with GCM like so: regid = gcm.register(SENDER_ID);
This gives me a registration ID (for example: "ABC"). If I try and re-register I get the same ID ("ABC"). If I clear the app data (in Androids app settings) and reload the app I get the same ID ("ABC"), however if I uninstall the app and reinstall, I get a new ID (for example: "DEF").
This is fine, however after registering the second time, my app will now receive notifications sent to both "ABC" and "DEF". This results in some in my app.
Is there a way to ignore all messages sent to any reg ID except the last one that was registered (in my example: "DEF")?
The example I am using to test is the official GCM-Client (https://developer.android.com/google/gcm/client.html).
There's no way to ignore the messages sent to the old reg id.
The best you can do:
In the client side, try to store some app data on the external storage. This would allow you to identify if the app was previously installed on the device, and to tell your server to replace the old reg id with the new one.
In the server side, handle canonical reg id responses from GCM. This won't prevent the sending of a message to an old reg id, but once you send a message to such reg id, you'll immediately remove the old reg id from your DB, and won't send any more messages to it.
I am started to exploring on GCM. Please clarify the following things.
By Registering with GCM server using the SenderID (Project ID get it from google API console), the Different device will giving unique registration id. I have used the following code to send message from server to all the devices by adding registration id as deviceid in the devicelist . I got the registration id of device by logging in the logcat.
Sender sender = new Sender("MY_API_KEY");
Message message = new Message.Builder().collapseKey("1")
.timeToLive(3)
.delayWhileIdle(true)
.addData("message",
"this text will be seen in notification bar!!")
.build();
MulticastResult result;
ArrayList<String> devicesList = new ArrayList<String>();
devicesList.add(deviceid1);
devicesList.add(deviceid2);
result = sender.send(message, devicesList, 1);
Is it right way to send message like above mentioned?
If that's the case how can design the code it will work after release the particular application? how can i get the registration id of all the devices after releasing?
Your server needs to keep track of all the registration ids from the devices. Therefore, you need a database table to store those registration ids. Then you need to expose a web service, or a HTTP POST entry point for your clients to upload their registration ids.
After a device successfully register with Google GCM server, you will receive the registration id in the onRegistered() callback method in GCMBaseIntentService. This is where you want to upload the registration id to your server.
I am trying to migrate to GCM in Android, C2DM now being deprecated. The registration process described here is different from registration described here. Are both registration same? Can we see code for GCMRegistrar to know for sure?
I've successfully migrated my C2DM project to GCM. Tested, it works fine. The only changes were:
in the Android app - change the value of sender upon registration
on the server side - change the auth header and the URL
That was it, as far as the interaction with Google goes. There were more some changes dictated by the app's logic:
in the Android app, the registration ID was cached in its preferences. Upon upgrade, I remove reg ID from the preferences to force re-registration, this time with GCM.
the logic of passing the reg ID to the server got an extra boolean parameter - if this is a C2DM or GCM reg ID
the logic of sending messages became conditional upon the said parameter.
Throwing out the C2DM logic completely out of the server would be unwise - not everyone upgrades their Android apps. The old, C2DM-enabled versions will be out in the wild for some time. And Google pledged to keep C2DM running in the short term. So message sending is conditional - depending on reg ID type, it sends either to GCM or to C2DM.
EDIT re: conditional logic:
if($RegID_Is_GCM)
{
$Auth = GCM_Auth();
$URL = $GCM_URL;
}
else
{
$Auth = C2DM_AUTH();
$URL = $C2DM_URL;
}
They are actually the same thing. The second one encapsulates the first one in a static method and registers a broadcast receiver. You can attach the source to the gcm.jar and see for yourself. You can find source code in ~/android-sdks/extras/google/gcm/gcm-client/gcm-src.jar
The Thing I like most in GCM is the RegID we will get from GCM server,it is not only an ID its an Address of this application on this Device. So this time you don't need to send a device Id to server along with your Registration Id as per was in C2DM.
In C2DM every time you request a registration id you will get a new ID.
But in GCM RegId generated by using your application package along with some device id so if you will request for Registration Id again and again you will receive the same RegId.
And if you uninstall an application and will install it again still GCM server will give you the same Registration Id.
So one Registraion Id will do no need of any Device Id to send to server.
I have been successful at migrating from C2DM to GCM. I have also documented how to implement GCM at
http://android.amolgupta.in/2012/07/google-cloud-messaging-gcm-tutorial.html
GCMRegistrar is just a helper that does the leg work described in the first page.
You can see the class here. android-sdk\extras\google\gcm\gcmclient\src\com\google\android\gcm.