We use GCM messaging to send remote commands to device. We have one particular client who uses the same model of devices from one manufacturer and with has 5.1 OS.
Our client registration process is pretty standard, that is once the client logs-in, it updates the GCM-Id to server and on server we have some commands that can be sent to the registered devices and internally it uses the registration id.
We are observing that even if the remote command is sent to one of the devices, it is being delivered to all these devices. The GCM Id on all these devices is different.
This does not happen with other devices (or we have not seen it yet)
If we use FCM Diagnostics and verify the lifecycle of message using the GCM-Ids of these devices we see that the same message ID has been delivered to all these devices.
We made sure that there is no ghost or random delivery from our backend, we verified backend logs and added extra logging as well.
Request for tips or hints, if anybody else saw such an issue earlier.
Try see this git on line 57, he uses json to sent a single message to multiples registration ids.
Example json content:
{
"data":
{
"from": "my_name",
"time": "0:56:23"
},
"registration_ids": ["id_1", "id_2", "id_3", "id_4"]
}
Lucas is correct in his example, the registration_ids is a parameter that specifies a list of devices (registration tokens, or IDs) receiving a multicast message. It can contain at least 1 and at most 1000 registration tokens.
Note: registration_ids are only for multicast messaging, not for
single recipients. Multicast messages (sending to more than 1
registration tokens) are allowed using HTTP JSON format only.
For more information, check this documentation.
Related
I am migrating from custom Push Notification to AWS SNS. I did the following.
configured AWS SNS Topic
Created Platform Application
created Endpoints
Suscribed endpoints to Platform Application
I am trying the last step for Pushing the Notification using 'publish' API for Ruby. I receive the message_id as response. It also logs as success / delivered in CloudWatch. But the Push is not received in the device.
The device is valid
The device has a valid push token
the device has the application installed.
The message format I tried areas follows
{"GCM"=>{"data"=>"{\"message\":\"message\",\"url\":\"url\"}"}, :default=>"default"}
SNS publish API syntax
client.publish({target_arn: endpoint_arn, message: message.to_json, subject: "SNS test", message_structure: :json})
FYI, Before marking this as duplicate of any other question, please note that i have referred all previous answers and nothing helped me. hence I am raising a new one.
The GCM payload format is updated.
This works for me.
{
"GCM": "{ \"notification\": { \"body\": \"hello....\", \"title\": \"title123\" } }"
}
There is a problem with my message formation. I figured it out by debugging with android . The Push reached the device but it was not in the expected format. So the push was not shown in the device. I was sending
{"GCM"=>{"data"=>"{\"message\":\"message\",\"url\":\"url\"}"}, :default=>"default"}
But the Android system was expecting 'badge' and some other keys in my message. I tried with
{:default=>"default", :GCM=>"{\"data\":{\"message\":\"test\",\"url\":\"https://s3.amazonaws.com/mcds_fulltext/aapg/gsaapgbull/issues/74/android_hdpi/cover_74.gif\",\"registration_ids\":\"arn:aws:sns:us-****-1:*********7:endpoint/GCM/gs*****_gcm/*********************\",\"badge\":\"10\",\"vol\":\"128\",\"issue\":\"10\",\"journal_name\":\"gsaapg\",\"abbr\":\"aapg\"},\"collapse_key\":\"New Article badge\"}"}
Now it works as expected.
This particular JSON might not be appropriate for everyone. But the cause of this issue is the message JSON is not in the expected format for the mobile app. This might be helpful for someone who face the similar issue.
As per my previously asked question, Firebase onMessageReceived not called when app is in the background , I need to change the payload to a 'data' payload as opposed to a 'notification' payload. (See link here -- What is the difference between Firebase push-notifications and FCM messages?).
The problem is, both the IOS and Android app we have utilize Firebase and the IOS app requires the push notification payload to use the 'notification' structure, while Android requires the 'data' payload structure.
My question is therefore, how do you distinguish between Android and IOS tokens / Ids obtained via the firebase sdk?
If our server saves these Ids and needs to send out a push notification, it needs to specify Android vs IOS in order to change the payload structure. Is the only way to accomplish this identification to have an app-based call to the server which differentiates IOS vs Android? Or is there a more sophisticated way using Firebase that will allow us to poinpoint which device it is?
Thanks all.
Information about an app instance is available from the Instance ID Service at this endpoint:
https://iid.googleapis.com/iid/info/IID_TOKEN
On success the call returns HTTP status 200 and a JSON object containing various status for the app instance including the platform:
returns ANDROID, IOS, or CHROME to indicate the device platform to
which the token belongs
I faced the same issue, following is my approach to solve the issue.
Firebase supports "Topic messaging", in which we can send data or notification messages to multiple subscribed devices.
Lets consider user login email id is unique (Lets consider example email id is test#gmail.com), In android application user will subscribe to test_gmail.com_data topic (replace '#' with '_' in email id since topic name doesn't support '#') and in iOS application user will subscribe to test_gmail.com_notification topic, From cloud functions I am sending Data message which is intended to android device on data topic and Notification message which is intended to iOS devices on notification topic.
By this approach I solved the issue, only problem with this approach is we end up sending twice the same message.
Example Code :
const data_message = {
data: {
"sender": "Narendra",
"Message" : "Simple data message"
},
topic:"test_gmail.com_data"
};
const notification_message = {
notification: {
title: "Announcement"
},
data: {
"sender": "Narendra",
"Message" : "Simple data message"
},
topic: "test_gmail.com_notification"
};
promises.push(admin.messaging().send(data_message));
promises.push(admin.messaging().send(notification_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.
I've got a server app that sends GCM push notifications. Each send of 1000 recipients returns a message that tells me the status of each registration ID. Some will have error codes. Is there a document somewhere from Google that tells me how I'm expected to handle these codes and what all the possible error codes are? My Google foo isn't turning up anything.
You didn't look hard enough. All the codes are explained here under Interpreting an error response.
I tried to copy and paste it in order for it not to be a link only answer, but the formatting is a bit off:
Interpreting an error response
Here are the recommendations for handling the different types of error
that might occur when trying to send a message to a device:
Missing Registration ID
Check that the request contains a registration ID (either in the registration_id parameter in a plain text message, or in the
registration_ids field in JSON).
Happens when error code is MissingRegistration.
Invalid Registration ID
Check the formatting of the registration ID that you pass to the server. Make sure it matches the registration ID the phone receives in
the com.google.android.c2dm.intent.REGISTRATION intent and that you're
not truncating it or adding additional characters.
Happens when error code is InvalidRegistration.
Mismatched Sender
A registration ID is tied to a certain group of senders. When an application registers for GCM usage, it must specify which senders are
allowed to send messages. Make sure you're using one of those when
trying to send messages to the device. If you switch to a different
sender, the existing registration IDs won't work. Happens when error
code is MismatchSenderId.
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.
Message Too Big
The total size of the payload data that is included in a message can't exceed 4096 bytes. Note that this includes both the size of the
keys as well as the values.
Happens when error code is MessageTooBig.
Invalid Data Key
The payload data contains a key (such as from or any value prefixed by google.) that is used internally by GCM in the
com.google.android.c2dm.intent.RECEIVE Intent and cannot be used. Note
that some words (such as collapse_key) are also used by GCM but are
allowed in the payload, in which case the payload value will be
overridden by the GCM value.
Happens when the error code is InvalidDataKey.
Invalid Time To Live
The value for the Time to Live field must be an integer representing a duration in seconds between 0 and 2,419,200 (4 weeks).
Happens when error code is InvalidTtl.
Authentication Error
The sender account that you're trying to use to send a message couldn't be authenticated. Possible causes are:
Authorization header missing or with invalid syntax.
Invalid project number sent as key.
Key valid but with GCM service disabled.
Request originated from a server not whitelisted in the Server Key IPs.
Check that the token you're sending inside the Authorization header is the correct API key associated with your project. You can
check the validity of your API key by running the following command:
api_key=YOUR_API_KEY
curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"ABC\"]}"
If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:
{"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
If you want to confirm the validity of a registration ID, you can do so by replacing "ABC" with the registration ID.
Happens when the HTTP status code is 401.
Timeout
The server couldn't process the request in time. You should retry the same request, but you MUST obey the following requirements:
Honor the Retry-After header if it's included in the response from the GCM server.
Implement exponential back-off in your retry mechanism. This means an exponentially increasing delay after each failed retry (e.g.
if you waited one second before the first retry, wait at least two
second before the next one, then 4 seconds and so on). If you're
sending multiple messages, delay each one independently by an
additional random amount to avoid issuing a new request for all
messages at the same time.
Senders that cause problems risk being blacklisted.
Happens when the HTTP status code is between 501 and 599, or when the error field of a JSON object in the results array is
Unavailable.
Internal Server Error
The server encountered an error while trying to process the request. You could retry the same request (obeying the requirements
listed in the Timeout section), but if the error persists, please
report the problem in the android-gcm group.
Happens when the HTTP status code is 500, or when the error field of a JSON object in the results array is InternalServerError.
Invalid Package Name A message was addressed to a registration ID whose package name did not match the value passed in the request. Happens when error code is InvalidPackageName.
EDIT (06/06/2015) :
A new error response codes table has been posted here.
The new error responses :
Device Message Rate Exceeded The rate of messages to a particular device is too high. Reduce the number of messages sent to this device and do not immediately retry sending to this device.
Topics Message Rate Exceeded The rate of messages to subscribers to a particular topic is too high. Reduce the number of messages sent for this topic, and do not immediately retry sending.
EDIT (07/21/2019) :
A new error response codes table has been posted here.
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.