My usecase: A user logged into my app, should be able to send messages to himself logged into the app on another Android device. If the user has more than one devices, then once he opens the message, the notification on other devices must disappear.
Doubts:
How to send data to a particular user across devices? I understand how to send messages to different users on different devices using GCM but this seems rather confusing.
How to achieve this in MQTT with adequate security? I read as much as I could about the security and got to the conclusion that MQTT isn't in the charge of it and that I've to implement my own security measures at the broker level. As of now Mosquitto broker allows username/password authentication, but for an app implementing Oauth, username/password seems rather vulnerable.
Or should I move over to XMPP?
You can use the new User Notifications feature of GCM.
What are User Notifications?
Third party servers can send a single message to multiple instance of
an app running on devices owned by a single user. This feature is
called user notifications. User notifications make it possible for
every app instance that a user owns to reflect the latest messaging
state. For example:
If a message has been handled on one device, the GCM message on the other
devices are dismissed. For example, if a user has handled a
calendar notification on one device, the notification will go away on
the user's other devices.
If a message has not been delivered yet to a device and but it has been handled, the GCM server removes it from the unsent queue for the
other devices.
Likewise, a device can send messages to the notification_key, which is the token that GCM uses to fan out notifications to all devices whose registration IDs are associated with the key.
Related
I am working on an app, which requires Android push notifications to be implemented.
I have decided to use Firebase Cloud Messaging directly; without using any other abstraction such as AWS SNS or Pusher.
I would like to avoid storing and managing device tokens in the backend, by using the following approach.
In the android app.
When the user logs into the android application, obtain device token but not send it to the server.
Subscribe to a topic that is based on a agreed convention, such that the topic is unique to that user.
On logout unsubscribe from the topic.
In the Server.
Whenever a situation arises to send a notification to particular user, send push notification to the topic, that is based on the convention.
I would like to know if this is a viable strategy to avoid managing device tokens ?
Case against using topics.
From the official docs.
Based on the publish/subscribe model, FCM topic messaging allows you to send a message to multiple devices that have opted in to a particular topic. You compose topic messages as needed, and FCM handles routing and delivering the message reliably to the right devices.
For example, users of a local weather forecasting app could opt in to a "severe weather alerts" topic and receive notifications of storms threatening specified areas. Users of a sports app could subscribe to automatic updates in live game scores for their favorite teams.
I see that topics are recommended, when multiple devices are to be notified. But I have decided to create a topic per user, this would mean most topics would end up getting subscribed by only one device; Is this approach ok ?
I see that topics are recommended, when multiple devices are to be notified
Yes, multiple devices that have something common to listen to, which is the topic. Topics are used for messages that could be received by the general clients since it is public -- i.e. anyone could subscribe and receive messages sent to it.
What is advised to use for multiple devices, but for the same user is to use Device Groups (see my answer here for tips on Managing Device Groups). However, if you don't mind the "topics being public" part, then your approach should be fine.
Yes, Here required device tokens if we want to send push notification whoever installed your app.
My research we can save device tokens in back end at first time installation of your app that is better according to my understanding so that we can easy to send push notification across all devices.
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.
I am learning how to implement the GCM both from client side (Android) and from server side (ASP.NET). I spent a bit of time on reading the whole google documentation related to GCM and I also tried the sample that they provided.
Because I need to integrate the GCM in an already existing app, I would like to know some specific stuff.
As I got it, the registration id is a token which ties the app on a specific device to the GCM service and the app server; so, the backend can send downstream messages directly to that device.
In my scenario, I could have multiple users who can use the app on the same device, that means they need to login in the app and they have an account on a database in the server side. Do I need to store a different registration id for each user on that device? Or still the registration id refers to only the app?
And what about the same scenario but distributed on multiple device, because a user can have multiple devices?
Thanks in advance.
This relates a lot to the context of your app and what you want to do with notifications
Having one registration ID per device will be okay.
I manage my multiple users by using subscription tags handled by my server.
So take the scenario if you have a sports app:
User A & User B share the same device. Each user subscribes to a tag.
User A is subscribed to two tags (Basketball & Football)
User B is subscribed to two tags (Tennis & Basketball)
When User A logs out you clear the tags associated with that user and when User B logs in you fetch his/her tags.
Your server knows notifications to send to the device based on the tags the user has subscribed for.
Multiple device scenario:
The same goes, when your user logs In you get their tags. The device also has its own token from GCM.
The registration id is the app's id, it may be changed if app version was updated. Your push notification will be sent on device with your app, regardless user account. So every user on every device will receive your notification, you must store only one refistration id per device.
For multiple users: If your messages are user specific, you would want to retrieve the user's token and subscribe to it only while they are logged in. When you switch users remove/unregister the previous token, then save/register the new user's token.
You should not only do this if you have multiple users per device, but when a user signs out. This will prevent user-specific messages being shown at wrong times to wrong users.
For multiple devices: it sounds like you are looking for Device Group Messaging.
With device group messaging, app servers can send a single message to multiple instance of an app running on devices belonging to a group. Typically, "group" refers a set of different devices that belong to a single user.
This is also nice because of the collapse_key. When one of the devices on the same account opens a notification, it will dismiss the notification on the other devices..
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!
Is there a way to rollback the notification request placed to GCM server?
As in, consider a GCM-message-request is placed to GCM server.
If the user sees the message in web before coming online in mobile, the GCM request should be rolled back. And user should not see the notification in mobile.
There is no built in mechanism for such rollback in the case you describe. You can try implementing it yourself - when your server notices the message was viewed in web, you can send another GCM message to the device with some data that represents a need to rollback. When you process that message, you should clear any notifications that were created by your app on that device (I'm not sure if that's possible, you'll have to check).
There is such a mechanism in a similar case - if the user has multiple Android devices, and you send a GCM message to all of them (using the new user notifications feature), once the user views the notification on one device, it would be automatically removed from the other devices.
If a message has been handled on one device, the GCM message on the other devices are dismissed. For example, if a user has handled a calendar notification on one device, the notification will go away on the user's other devices.
If a message has not been delivered yet to a device and but it has been handled, the GCM server removes it from the unsent queue for the other devices.