I am working on push notifications with Google Cloud Messaging(GCM). I am able to setup server and client side following this tutorial.
The server runs on Apache Tomcat6.0 (localhost) and Android emulator on Google APIs (API level 17). I have a sender id and API key. When run from the emulator, I get a successful device connection message. Sooner after that, upon sending message from server shows the following error.
com.google.android.gcm.server.InvalidRequestException: HTTP Status Code: 401()
com.google.android.gcm.server.Sender.sendNoRetry(Sender.java:211)
com.google.android.gcm.server.Sender.send(Sender.java:125)
com.google.android.gcm.demo.server.SendAllMessagesServlet.doPost(SendAllMessagesServlet.java:83)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
From other posts, I understand wrong API key is the culprit. But in my case, I made sure I am using the right one from the API console.
By the way, when I run the emulator, I saw a message 'sending regId to server'. What is the registration id? It is not same as sender id; looks like an encoded one.
Any break through?
EDIT
The issue is finally solved! Ant was not properly building the WAR file. So API key hardly gets updated. It was hell of a nightmare to spot the bug. Thanks all for the inputs!
I suggest you to read the GCM guide:
GCM guide for Android
The sender ID is a constant that is going to be used in the comunication between GCM and your server. The regsitratiomID (regID) is managed by the GCM service when your phone registers to his service.
A better definition:
http://developer.android.com/google/gcm/gcm.html
Sender ID:
A project number you acquire from the API console, as described in Getting Started. The sender ID is used in the registration process to identify an Android application that is permitted to send messages to the device.
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 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 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.
The Sender ID is the project number what you have created under Google console.
Registration ID
When your application registers to the GCM it gets the registration ID. To deliver the message this registration ID will be used by the GCM to identify your device + your application.
Your android app should send this registration ID to your server so that when server want to send you a message it can tag it with the registration ID, and hence the GCM can deliver it to the right device & right app.
Diagnose whether the registration ID is successfully shared with the server (Get/Post), unless you won't receive any message.
Related
I am completely new to push notifications, FCM and Ionic.
I have followed this tutorial to create a push notification using Ionic 2 and it works.
It feels like there is no use of device-id (generated at the client side) at the server side in this ionic doc.
I am unable to understand how to send different push notifications to different users using the same app and same server code?
Also whats the purpose of FCM (Server key and Sender ID) here?
What's the exact workflow, does it works like a web-socket?
Thanks for the guidance :)
1. It feels like there is no use of device-id (generated at the client side) at the server side in this ionic doc.
The device-id (aka the Registration Token) is the identifier for the specific device you intend to send the push notification to. Saving this value in your App Server is important so that you can send push notifications specifically towards it (should you decide/need to) later on.
2. I am unable to understand how to send different push notifications to different users using the same app and same server code?
As mentioned above, this is where the device-id (Registration Token) comes into play. For each device, there is a corresponding unique id, which you'll have to specify in your payload.
3. Also whats the purpose of FCM (Server key and Sender ID) here?
You can refer to the FCM docs for these:
Server Key - A server key that authorizes your app server for access to Google services, including sending messages via Firebase Cloud Messaging. You obtain the server key when you create your Firebase project. You can view it in the Cloud Messaging tab of the Firebase console Settings pane.
Important: Do not include the server key anywhere in your client code. Also, make sure to use only server keys to authorize your app server. Android, iOS, and browser keys are rejected by FCM.
Sender ID - A unique numerical value created when you create your Firebase project, available in the Cloud Messaging tab of the Firebase console Settings pane. The sender ID is used to identify each app server that can send messages to the client app.
To keep it short, Server Key is for authenticating, Sender ID is for identifying from which project the message is coming from.
4. What's the exact workflow, does it works like a web-socket?
Not really. Having a web-socket means that having the connection always active until decided to be closed, where in FCM (or even before, GCM), the lifecycle is like this:
Lifecycle Flow
Send and receive downstream messages.
Send a message. The app server sends messages to the client app:
The app server sends a message to GCM connection servers.
The GCM connection server enqueues and stores the message if the device is offline.
When the device is online, the GCM connection server sends the message to the device.
On the device, the client app receives the message according to the platform-specific implementation. See your platform-specific documentation for details.
Receive a message. A client app receives a message from a GCM connection server.
Send and receive upstream messages. This feature is only available if you're using the XMPP connection server.
Send a message. A client app sends messages to the app server:
On the device, the client app sends messages to the XMPP connection server. See your platform-specific documentation for details on how a client app can send a message via XMPP.
The XMPP connection server enqueues and stores the message if the server is disconnected.
When the app server is re-connected, the XMPP connection server sends the message to the app server.
Receive a message. An app server receives a message from the XMPP connection server and then does the following:
Parses the message header to verify client app sender information.
Sends "ack" to the XMPP connection server to acknowledge receiving the message.
Optionally parses the message payload, as defined by the client app.
I am unable to understand how to send different push notifications to different users using the same app and same server code?
It's your task. Your message must contain all neccessary data (i.e. userId) so your app knows which of the users are target for that message.
I have used gcm demo code for viewing working of different features of gcm.But unfortunately it is showing some error.My client side is gcm quickstart code ,which is working finely,successfully sent notification using command code(gcm sender) .But i have few doubts-
Is it possible to send message/notification from gcm demo code to gcm quickstart?
2.I have used sender id and api key of gcm quickstart for sending notification from gcm demo.
3.Is there any correction required in gcm demo?
As GCM Reference 401 is authentication issue and possible problems are explained below;
The sender account used to send a message couldn't be authenticated.
Possible causes are:
Authorization header missing or with invalid syntax in HTTP request.
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 Authentication header
is the correct API key associated with your project. See Checking the
validity of an API Key for details.
We are developing apps both in IOS and Android. GCM push notification has been enabled for IOS and its working fine now. The package name for both the platforms are going to be the same.
I was given SERVER API KEY and SENDER ID by ios developer to set up gcm for android. While looking for the steps, I came across https://developers.google.com/cloud-messaging/android/client.
I kept to myself that the steps listed in the contents need to be done to set up GCM for android (please correct me if I am wrong).
Get Config file and add it to Android project
Set up Google play services (I added gcm in my project dependency)
Add entries to Manifest file
Check for google play services APK
Obtain registration token.
"An Android application needs to register with GCM connection servers before it can receive messages"
"The client app should store a boolean value indicating whether the registration token has been sent to the server." - My backend team told me I dont need to send them anything I have to just configure gcm in the app and the app will receive messages from backend.
So, My question is Do I need to have RegistrationIntentService and MyInstanceIDListenerService. Also, Do I have to define my InstanceIDListenerService in Manifest?
Our backend uses device id to send push notifications to devices so they dont need registration token to be sent to them as we send device id. So in this case, Should I register my app with GCM using RegistrationIntentService and InstanceIDListenerService? if so, should the app keep the registration token with itself. Is this registration needed?
GCM supports three types of downstream (server-to-client) messaging: send to a specific device (also called "simple" or "targeted"), send to a topic, or send to a device group. Your question says, "our backend uses device id to send push notifications to devices". It is not clear what "device ID" is and which type of messaging you intend to use. Your backend team has told you that you "don't need to send them anything". If that is true, I don't know where they are getting the "device ID".
Each of the three types of messaging provided by GCM require client devices to register with GCM and obtain a registration token. To send a message to a specific device, the registration token is effectively the "device ID". So yes, you need to implement something similar to the RegistrationIntentService and InstanceIDListenerService described in the documentation.
The description in the documentation about needing to send the registration token to the App Server is misleading. That is only required for targeted messaging. The documentation for receiving topic messages states: "Note that, for topic messaging it's not required to send the registration token to your app server; however, if you do send it, your server can verify the validity of the token and get more information about the app that created it."
This question already has answers here:
Do old GCM tokens live on even after an uninstall?
(2 answers)
Closed 7 years ago.
I'm currently trying to use GCM to send notification to user and currently I'm still studying on how I can maximize it. For now I just use the sample project provided on the documentation here and I use the gcm-client sample to work on it.
Now using this project from Git I tried to push a message using the registration ID created by the app and yes it successfully delivers the message.
Now the problem is that after I uninstalled the application. After I reinstall it it will generate a new registration ID wherein I store it on a server together with the previous one except that I can't tag the previous registration ID to not receive any further message since the uninstall might happen when user has no internet connection. After that I send a message to two registration ID's which is the ID before uninstalling the app and the ID after reinstalling the application. What happen is that I receive two push messages eventhough I expected it to only get one since the app already changes the registration ID.
I expect that the app might receive twoor more duplicate apps if ever I also updated the app since as said on documentation the registration ID might change on update.
Any workaround I can do to handle this duplicate messages?
From the official documentation:
How uninstalled client app unregistration works
A client app can be automatically unregistered after it is
uninstalled. However, this process does not happen immediately. What
happens in this scenario is:
The end user uninstalls the client app.
The app server sends a message to GCM connection server.
The GCM connection server sends the message to the GCM client on the device.
The GCM client on the device receives the message and detects that the client app has been uninstalled; the detection details depend on the platform on which the client app is running.
The GCM client on the device informs the GCM connection
server that the client app was uninstalled.
The GCM connection server
marks the registration token for deletion.
The app server sends a
message to GCM.
The GCM returns a NotRegistered error message to the
app server.
The app server should delete the registration token.
Note
that it might take a while for the registration token to be completely
removed from GCM. Thus it is possible that messages sent during step 7
above get a valid message ID as a response, even though the message
will not be delivered to the client app. Eventually, the registration
token will be removed and the server will get a NotRegistered error,
without any further action being required from the app server.
However, it can apparently happen that you still get the notification for the old registration ID, as users state in other questions:
Android GCM and multiple tokens
Unregistering and re-registering for GCM messages causes two regId's to be valid. Is this as intended?
Do old GCM tokens live on even after an uninstall?
For this problem, there is a functionality called "canonical IDs":
Canonical IDs
If a bug in the client app triggers multiple registrations for the
same device, it can be hard to reconcile state and the client app
might end up with duplicate messages.
Implementing canonical IDs can help you more easily recover from these
situations. A canonical registration ID 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.
#KaHel When client app was uninstalled regId will be valid during some time, you are right. But, when client app will be installed again and your push server try to send message on old reg id that message will be successfully sent but GCM server put cannonical_id in response. And you should correct processes this response with cannonical_id. How do this i described at this post and there is not big documentation about cannonical_id. I.e. as soon as you get cannonical_id from GCM server you should immediately replace old reg_id by new one value. It will allow you not to produce a many regIds for one client, just one to one.
After reinstal you will get new RegId and prev not valid anymore. So, even if you send push to both RegIds, only last will received it.
You can implement logic for accounts in application.
For example, when user login in application you send his GoogleId + RegId. After reinstall of application and relogin you just update RegId on server. So, you can have only one RegId for every user.
There is problem: only one device will receive push msg (if you login in 2 devices with same account). So, you can send to server GoogleId + RegId + DeviceId after start application.
All,
I'm probably asking a very basic question here, but how does one get your device ID for PushSharp in Android? My setup is VB.net, and we'll be sending to a large number of different Android devices.
Following the PushSharp example here is my code so far:
push.RegisterGcmService(new
GcmPushChannelSettings("YOUR Google API's Console API Access API KEY for Server Apps HERE"));
push.QueueNotification(new GcmNotification().ForDeviceRegistrationId(
"DEVICE REGISTRATION ID HERE")
.WithJson("{\"alert\":\"Hello World!\",
\"badge\":7,\"sound\":\"sound.caf\"}"));
I know the API key is from the GCM service, but where does the Device Registration ID come from? Is that setup by the GCM service? Or is that something the android device sends the server should save?
Thanks for the help.
The registration ID is assigned by the GCM service. When the application registers to GCM, it gets a registration ID and should send it to the server.
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.
You can read more about it here.
In case you ended up reading this post and could not get yourself sorted out with the selected answer, here is the ultimate link that helped me:
Getting a GCM registration ID