Prevent GCM client displaying messages from old reg ids - android

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.

Related

Firebase Device Groups messaging works even if device registration ID does not work/ was updated

I'm using Firebase Messaging's device groups to send messages right now, and I've run into an issue where device group notification keys will still successfully send a message to devices even if their device ID has been updated.
An example would be like this:
Install app on Device A and get Device_A: device_registration_ID = "25".
We create a device group with Device A device_group_1: registration_key = "group1".
Sending a message to device_group_A will result in a success.
We delete and reinstall the app
The old device_registation_ID = "25" is now invalid, and a new one is created by Firebase Device_A: device_registration_ID = "100"
I create a new device group with Device A device_group_2: registration_key = "group2"
Sending a message to device_group_2 is a Success
Sending a message to device_registration_ID = "100" is a Success
Sending a message to the old device_registration_id = "25" is a Failure as we expect
However, sending a message to old device_group_1 is still a Success
Why does the old device_group_1 still work? The old device_registration_ID doesn't work anymore, so how does the device_group_1 even send a message to my device?
I want to maintain Device Groups such that when an app is deleted or a device_registration_ID is replaced the respective Device Group can be updated as well. I wanted to do this on the server side (Ie. check for failures when sending messages and comb through the failures to update my device_registraiton_IDs) because relying on the client code can result in some misses (Ie. if the client uninstalls the app while offline, there's no way to update the server). However, right now there's never any failures for device group messaging because even with defunct IDs they still somehow work!
Is there any other way I update my device_registration_IDs on the server side, preferably through messaging failures?
EXTRA. Creating a device group with a defunct device_registration_ID results in a no valid registration id

Get GCM canonical registration ID without sending a message

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.

Gcm device registration issue in android

Currently i am working with push notification in android.its working fine.but my issues is am getting multiple notification instead of a single notification.then i check my device registration table and find a strange fact ,after each 30 minutes my device id is changing,so multiple device are resisted for same user_id and getting number of notification together .i don't know why this happen.i am using Samsung galaxy s2 for testing. please help me .
I'm not sure why your registration id changes every 30 minutes. Perhaps if you post your registration code I'll be able to tell.
Regardless to that issue, your server should be able to handle multiple registrations for the same device. When you send the registration id to your server, send with it another unique id created by your app or by your server, and that would allow you to identify when you get a new registration id for an existing device, in which case you'll replace the old registration id with the new one.
Another thing you should do at the server is handle the case where gcm server returns a canonical registration id, in which case you should replace the id you used for sending the message with the canonical one.

Canonical Registration ID and message ID format

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.

Registration confusion Android GCM

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.

Categories

Resources