Unique Firebase Instance-Id for every user account - java

I'm unsure how to handle different user accounts on the same device appropriately, as Firebase only creates one Instance-Id per device.
Therefore, I though that it would be possible to delete the Instance-Id when the user is logged out and to create a new one when a new user is logged in.
On login:
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> System.out.println(task.getResult().getToken()));
On logout:
FirebaseInstanceId.getInstance().deleteInstanceId()
Does Firebase ensure that the Instance-Id will be unique, even if it is generated multiple times on the same device?
The reasons why I prefer this approach are that it's simple to unsubscribe the user from all topics at once and moreover push notifications can be addressed to a specific user.

Does Firebase ensure that the Instance-Id will be unique, even if it is generated multiple times on the same device?
Regenerating an Instance ID will indeed always result in a unique value. As long as you ensure that you delete the Instance ID when the user logs out, you'll get a fresh token next time around.
To ensure your token registry (the place where you store tokens) doesn't accumulate too many outdated tokens, be sure to either remove the token when the user signs out, or when you find out a token is no longer valid when sending messages. See my answer to this question.

If you want to have Unique FCM Instance Id for each user on a device, you should call FirebaseInstanceId.getInstance().deleteInstanceId()
on each logout on an account.
Then in next FirebaseInstanceId.getInstance().instanceId
call, you'll get a new unique Intance Id
But there is a point that you need to know. Call deleteInstanceId() on a new Thread, not MainThread

The best way to handle your issue, is to use topic messaging.
From the 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.
When the user logs in the app, you can subscribe to a certain topic, for example:
FirebaseMessaging.getInstance().subscribeToTopic("weather")
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
String msg = getString(R.string.msg_subscribed);
if (!task.isSuccessful()) {
msg = getString(R.string.msg_subscribe_failed);
}
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
Then the user can receive notifications based on the topic name. Then when the user clicks the logs out button, you can call the following:
FirebaseMessaging.getInstance().unsubscribeFromTopic("weather");

Related

Android/Java: how to send notifications to user, even when app is not "actively" being used?

I want to be able to send a notification to a user IF something changes.
For example, my application is crime-related. So users can submit reports of crimes that have happened in their neighborhoods.
When a new crime is reported, I want to be able to send ALL users in that specific neighbourhood a notification, even if they are not actively using the app.
How can this be done? I'm quite new at this but to my understanding services like Firebase Messaging require you to type out a message manually and select users to send the message to manually. I'm wondering if there's a way this can be done without someone having to manually do work?
Similar to how snapchat/instagram and stuff will send you notifications that someone has sent you a message even when you are not using your phone.
In my case, I just want the same standard notification "New crime in your area" to be displayed...
How can I do this? (Currently for notifications I'm just using Notification Channels), thank you so much!
You can easily do this using Parse Server through FCM integration.
First, you need to setup your Android app to be able to receive push notifications
Just follow this Quickstart: https://docs.parseplatform.org/parse-server/guide/#push-notifications-quick-start
Second, you need to create a cloud code function
I suggest you to create a cloud code function that will receive the neighborhood as parameter, will query for the user installations in that neighborhood and send the push notification to all of them.
It would be something like this:
Parse.Cloud.define('notifyCrime', async req => {
const query = new Parse.Query(Parse.Installation);
query.equalTo('neighborhood', req.params.neighborhood); // I'm supposing you have a field called neighborhood in your installation class - if not, you can save this field there when the user sign up
await Parse.Push.send({
where: query,
data: {
alert: 'There is a crime in your neighborhood'
},
useMasterKey: true
});
});
Reference: https://docs.parseplatform.org/js/guide/#sending-pushes-to-queries
Third, you need to call the cloud function from your Android app
Once some user has reported a crime, you can call the cloud code function that you created in step 2 to notify all other users in the same neighborhood.
It would be something like this:
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("neighborhood", "The neighborhood goes here");
ParseCloud.callFunctionInBackground("notifyCrime", params, new FunctionCallback<Object>() {
void done(Object response, ParseException e) {
if (e == null) {
// The users were successfully notified
}
}
});
Reference: https://docs.parseplatform.org/cloudcode/guide/#cloud-functions
"my understanding services like Firebase Messaging require you to type out a message manually and select users to send the message to manually".
This is not completely true. There is a method name Firebase Topic Messaging, that lets you send notifications to specific user segments only. You have to register from the app for that topic and then, you can send customized message to your user groups based on topics they subscribed to.

Can we send notifications in android using Firebase's UID instead of registration token?

I have two android applications in my single firebase project. That project belongs to the connection of vehicles. One app is for the driver and other app is for the passenger. So whenever passenger requests for a ride the driver needs to be notified of that request. So is there any way to send notification to the driver using firebase UID instead of FCM registration token.
I want to know whether registration token will be fix for a particular user or it will refresh/change over time.
Yes you can, use this to register the UID as a topic:
FirebaseMessaging.getInstance()
.subscribeToTopic(appUser.getUid());
Now, when sending the notification, you can use this topic to send the notif. to the particular user.
Tokens keep on refreshing at instances, topics defined by you will not change. Every device for which the topic is defined will be notified.
NOTE:
Registering too many topics will raise
messaging/too-many-topics error. Details here. Hence, token
registration in the preferred way.
Fetching and keeping track of tokens:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(String s) {
super.onNewToken(s);
// Save the new token here in a place from where you want to fetch it and send notification
Log.e("NEW_TOKEN",s);
}
}
The answer is No. The FCM tokens are device generated tokens which is generated when,
App is installed
App Data is cleared
and UID is a unique identification generated from a particular user account. Both are not related to each other.
As per your problem, you need to store your tokens wrt to UID and then use it to send notification. Or you can use subscribe tokens for seperate user group. Thats the only option I see.

Getting the List of registered devices from fcm for my site

I am new to FCM and mobile coding. This is what I am trying to achieve:-
Develop an app to allow users to select some events.
I have a site that will loop through the events for users. When an event is close to its start time or some messages were created for
that event, I will send a FCM message to all the devices that
registered to that event.
I am confused on the implementation. This is what I am thinking:
When my app starts, I can register for push notification and it will return a devicetoken.
When user saves an event I can pass the devicetoken back to the server to re remember it.
In my site's code, I have some code to detect if an event is close and sends notification base on the devicetoken linked to
that event.
Is this about the right way to code? But if the user restarts the app or restarts the phone, isn't that I will get a new devicetoken? So I need to store some other identifier to identify a user (e.g. google plus user name)?
Is this about the right way to code? But if the user restarts the app or restarts the phone, isn't that I will get a new devicetoken? So I need to store some other identifier to identify a user (e.g. google plus user name)?
Yes it is right, and check the below for the questions:
You need to use FirebaseInstanceIdService it is used to handle the creation, rotation, and updating of registration tokens.
To retrieve the token of a device use this:
FirebaseInstanceId.getInstance().getToken()
The above token that you get may change in the following situations:
Instance ID is stable except when:
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
Then using this method inside FirebaseInstanceIdService, it will refresh the token whenever any one of the situation happens:
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
After you've obtained the token, you can send it to your app server and store it using your preferred method.
more info here: https://firebase.google.com/docs/cloud-messaging/android/client

Android/Firebase - Check to see if you are subscribed to topic

I am wondering if there is a way to test to see if you are subscribed to a topic on the android side of things.
Basically, I am HOPING that all devices will subscribe to a topic during their installation, when the token is first obtained by the device. However, there is always a chance that the device fails to subscribe. The FCM registration token should be installed on the device for a long time, and thus, the onTokenRefresh() method shouldn't be called again without clearing data, uninstall/reinstall, etc.
My idea was to test to see if the device is subscribed to a topic in my MainActivity, and if not, then try to subscribe again. If it fails to subscribe, then get a new token and try again, etc.
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.e(TAG, "Refreshed token: " + refreshedToken);
// Subscribe to a topic
Log.e(TAG, "Subscribing to topic");
FirebaseMessaging.getInstance().subscribeToTopic("test");
So, I can subscribe and unsubscribe, but how do I check if the device is subscribed to a topic? I did my fair share of googling, and couldn't find anything, unfortunately.
I would greatly appreciate any/all assistance. Thanks!
There is currently no way to check on the client side if they are subscribed to a topic.
The behavior for subscribeToTopic is it would immediately subscribe to the specified topic, if it fails, it would retry on it's own (unless your app was killed). See my answer here.
I think that forcing the onTokenRefresh call just to make sure that subscribeToTopic is too much. You could simply just call it in your initial activity if you want, that way, everytime the app starts, it sends the subscription request.
Actually this can be done by using this api: https://developers.google.com/instance-id/reference/server#get_information_about_app_instances
As IID_TOKEN you need the FCM token and in the header you have to pass Authentication: key=YOUR_SERVER_KEY. You can find the server key as described here: Firebase messaging, where to get Server Key?.
Don't forget to include details=true as query parameter in the url, otherwise the topics won't be included in the response.
I would recommend writing a Cloud Function to encapsulate it, so you don't deploy your server key to the client.

How to send a message to a specific user of an FCM (Firebase Cloud Messaging) token?

The issue is that FCM provides a token for each unique app for a device, so let's say two users use the same device and application, one signs out so that the other can sign in and use the app, i'm confused about how the flow should go! now the two users have the same token so both of them will receive the upcoming messages.
A similar question was asked here and here but it's still not clear for me!
Any help will be appreciated.
Generate a user specific unique code to each user by yourself at the time of login.send the user specific unique code along with the push notification from server end.
Now send push notifications to all users.and when notification receives check check the user specific unique code to identify the user
When the App is killed, then by default Android will shows the 'notification data' as Notification, So the 'notification data' should be common to all users.
User specific data should be added as 'data message'.When a push notification arrives, the default Notification will be shown.And the 'data message' will get through the Intent in the launcher activity.Here you can identify the user by the user specific unique code and respond to push notification.

Categories