So I have a situation which I didn't think would happen based on my understanding of the registration My understanding:
Phone Registers with google gets registration_id, send registration_id to the server, use registration_id when sending out push notifications. If registration_id is updated by google, they will send a new registration broadcast.
However, I have case where a phone was registered, and was successfully receiving push notifications, but than one day the server goes to send a push notification to the phone and I get a error "NotRegistered" which would suggest the registration_id refreshed but did not get propagated through the system properly, whether it be on the phone side or the server side.
My question is has anyone else hand issues like this? What is the best approach to making sure this doesn't happen?
From the Android Cloud to Device Messaging Framework documentation:
Note that Google may periodically refresh the registration ID, so you should design your application with the understanding that the REGISTRATION Intent may be called multiple times. Your application needs to be able to respond accordingly.
Related
My Android client app does not receive any Firebase push notifications targeting topics, however I immediately receive notifications sent to all app users or notifications sent to specific devices.
I didn't change anything in my code and I checked whether the client is correctly subscribed to topics.
For further details about my subscription logic:
In order to make it easy for my web service to send notifications to a specific user, each user is subscribed to a topic entitled with his user-id whenever he logs in from the client app.
Is this approach weak somehow? Should I otherwise register the device token to my database every time it's updated? And then send the notification to that specific token?
Should I otherwise register the device token to my database every time it's updated? And then send the notification to that specific token?
It is highly suggested that developers save the generated registration token for each device for later use. As mentioned in the docs:
After you've obtained the token, you can send it to your app server and store it using your preferred method.
In your case, it is preferable. It'll remove the added action of subscribing the device to a topic. Plus it can be useful to track the message status using Diagnostics tool should you need it in the future.
Scenario: I have a 3rd-party app server, a gcm http connection server, and an android app setup for push notifications. When the user uninstalls the app, I can delete them from my 3rd-party server by sending their (no-longer-valid) registration id a push notification and handling the "NotRegistered" error returned from the gcm connection server.
However, this similar approach does not seem to work when you send a push notification to users subscribed to a "Topic", as here the gcm connection server only returns a json object with the "message_id".
The notable columns in my 3rd-party server database table are as follows:
| gcmRegistrationID (string) | subscribedToNotificationTopic (boolean) |
Does anyone know how to identify a user that has previously set true in the subscribedToNotificationTopic column, then uninstalled the app?
I have an idea on how to resolve this, but it seems somewhat messy.
Every so often, instead of only sending push notifications to a topic e.g.
{
"to" : "/topics/global",
...
}
send a push notification to the registration ids of the users subscribed to the topic e.g.
{
"registration_ids" : {list of registration ids},
...
}
such that I can retrieve and handle any "NotRegistered" errors.
The problem with this however, is that multicast messaging has a limit of 1000 users so I'd have to send a message for each thousand.
This seems like bad practice (especially if there is more than one topic involved), but maybe it's the only way?
(Extra tags: topic messaging, pubsub, unregister, google cloud messaging)
First off, I am not sure it is correct to assume that an "NotRegistered" error can only be the result of the user uninstalling your app. It seems like the device can become unregistered if the device receives a message but that message can not be delivered. This can happen if the user stops the app (which is different from uninstalling it, or even if the app was killed and remains stopped due to a power saving mode.
https://developers.google.com/cloud-messaging/ccs#response
If it is NotRegistered, you should remove the registration ID from
your server database because the application was uninstalled from the
device, or the client app isn't configured to receive messages.
What you can do is from the device side, periodically register the device, and make sure that the token you get back is the same as the one you stored, if not update your server with the new token.
As far as detecting if a user has uninstalled your app via a response to a topic message, I agree with you it does not seem to be directly possible. As an alternative to your proposed solution, you might, every now and then include a flag in the topic message that would ask the device to validate itself with your server, if a device does not validate itself after some number of attempts or some period of time you might conclude the user is not longer listening.
The other question is why do you really need to know. Is there any harm in sending some extra regid's to google? If a user quits your web service you can remove them from the list, but do you really need to take action if they just un-install your app from there device? - Just some thing to consider. Hope this helps.
For the application that I am working I need to integrate Google Cloud Messaging. After playing a little with different examples, I was able to send and receive a notification on my deivce.
However, I have come across an interesting situation. As I know (please correct me if I'm wrong), the registration_id is issued per device and per application.
The application that I'm working supports login functionality. When the application is installed and the user logs in for the first time (let it be "UserA"), I request the registration_id from GCM which then I send it to my server.
Now imagine that UserA logs out and gives his device to some UserB to log in. With other words, UserB logs in using UserA's device.
The problem is that if meanwhile UserA receives a notification, UserB will be able to intercept it. And if UserB receives a notification, he won't be able to receive it.
This seems normal because the registration_id is per device and per application, but it does not seem reasonable for my case.
So I'm asking if there is a way I could make the registration_id to be dependent of some user id (besides the device and app)? Or how could I make such that the logged in user to receive only his own notifications?
Yes its true that you have one google registration ID for the app per device.
But you can always register and unregister users at your own Server that will actually send messages to GCM and GCM will send this to the registered devices.
Define some interfaces for your Server like registerOnServer and unRegisteronServer , send some unique value for each user on this interface.
So, in your case, when A use Log ins , regitration is done on GCM first and register the user on your Server with registerOnServer inteface and while the user is logged in send notifications pertaining to him to GCM to be send to the device.
When A logs out, unregister him using unRegisterServer and do not send any messages from your Server to GCM as A is unregistered.
So,now if B Logs in even with the same device , register him at your Server and send his messages.
This shall solve your problem!
I am trying to write an application which notifies a cellphone using GCM. I was able to implement basic functionality, but there is one question I'm still unsure of
As I understand, the flow goes like this:
Device start up
Device registers, obtains registration id
Server gets the knowledge of registration id on device
Server is using it's API key + registration id to send payload to device
Device receives payload.
One thing which is unclear to me is: what is a proper methodology to implement step #3?
I could not find any way to obtain a list of registered devices. Lets imagine, I am using GCM for a purpose of posting to a known device, and I could email that ID to myself and then register it on the server manually. But as I understand, it expires.
So, it there an expectation that I have to keep re-registering and somehow notifying server every time it happens?
Yes, your app on device must send registration ID to your server application in order for server to be able to send GCM messages. See third point in Enabling GCM.
Here's the situation I'm struggling with. When a user installs my app and runs it for the first time, I register with C2DM and get the registrationID. I then send it to my server and notifications are sent to the app.
If the user uninstalls the app, then installs it again, a new registration is made to C2DM and I receive a new registrationID.
The problem is, the server now has two registrationID's for the same app and I get multiple/redundant notifications to onMessage.
What is the best practice way of avoiding this situation?
When we send the registrationId to our server we generate an identifier that can be constantly reproduced client side to identify the registrationId to the specific user. This also allows us to unregister the user if we wanted the option, as a plus it eliminates your issue.