Android firebase token refresh failed - android

Android firebase token refresh.
If any new token generated from firebase, it will call the onTokenRefresh and service will update the token to server.
Is there any way we check firebase directly from server to get the new tokens generated for clients with old tokens ?
If the mobile switched off for sometime and fire base tried to send the refresh token but it failed.
How fire base will send the token in that case. will it keep try until it send the new token to device ?
Thanks

If the mobile switched off for sometime and fire base tried to send the refresh token but it failed. How fire base will send the token in that case. will it keep try until it send the new token to device ?
The Firebase servers don't send fresh tokens to devices. Instead, the Firebase SDK inside the device/app requests a new token when it detects that this is required. So this will only happen when the device is turned on.

Related

send cloud message (FCM) multiple devices single user

I have an application which is already built. Now I want to use FCM to send messages between server and users.
As I understand each device has its own token which I can use to send message, and this token can be retrieved from
FirebaseInstanceId.getInstance().getInstanceId()
Correct me If I am wrong.
The application and backed server works fine and bellow my workflow
1- User open the android app.
2- Android app take the user token ID for authentication and device token for
messageing and send them to the server.
3- The back end server verify the user via
decodedToken = FirebaseAuth.getInstance().verifyIdToken(login.getToken());
then it save the token for sending the message.
Sending message working fine until I stuck with the following scenario.
The application allows multiple devices to login with same user, which means for 1 USER can have multiple tokens for messaging.
In this case I want to send message to all devices logged in with this user.
So how I can do this without changing the current design of my application
You need to change your DB and add ability to save all device tokens from one user. Then you need to call this Firebase api https://fcm.googleapis.com/fcm/send as many times as the tokens user have. Here the official documentation.
https://firebase.google.com/docs/cloud-messaging/http-server-ref
To update device specific token when it is changed on client side, you also have to bound that token with the deviceID, so to have that you need to pass the DeviceId to the server when passing the Firebase token. As deviceID can serve Android unique deviceID, or the id that provides Firebase in client side FirebaseInstanceId.getInstance().id. And here how to get Android deviceID
Is there a unique Android device ID?
If you use access_token for login the user, as another alternative, you can bound firebase token with user access_token, as it is unique for any device the user logged in.

Is there a way to inform directly the server from changes on registration ID for a device?

I have an application that uses FCM to receive messages from a custom server. There are some situations when a new registration ID is generated (https://firebase.google.com/docs/cloud-messaging/android/client#sample-register). I can monitor this change from mobile side (https://firebase.google.com/docs/cloud-messaging/android/client#monitor-token-generation).
My problem is that I would like to monitor that new token generation from server side. Does Firebase offer this possibility?
There is nothing built in to Firebase to signal the generation of a new Instance ID token to server-side code.
If you want a server to respond to a token change, you will have to call that server-side code from your FCM client. Note that all token generation is initiated by the client anyway, so you wouldn't be getting called any sooner or more frequently anyway.

Xamarin Form: Android using Firebase Cloud Messaging not receiving message

I have made the Firebase Cloud Message Notification working even work through the Notification Hub from Azure. The time I can't receive the message is when I try to re-run the application.
Process:
1) Fresh install the application with Visual Studio IDE
2) Stop the debugger
3) Debug and run the application again through Visual Studio IDE
4) Send a test message through FCM Console
If I am not doing 3, I still can receive the message even if the application is in background
LoadApplication(new App());
            FirebaseOptions options = new FirebaseOptions.Builder()
            .SetApplicationId(GetString(Resource.String.fcmAppId))
            .SetApiKey(GetString(Resource.String.fcmApiKey))
            .SetGcmSenderId(GetString(Resource.String.fcmGCMSenderId))
            .Build();
            FirebaseApp.InitializeApp(Android.App.Application.Context, options); 
?
public class MyFirebaseInstanceIdService : FirebaseInstanceIdService
{
    const string TAG = "MyFirebaseInstanceIdService";
    public override void OnTokenRefresh()
    {
        var refreshedToken = FirebaseInstanceId.Instance.Token;
        Settings.NotificationToken = refreshedToken;
        Android.Util.Log.Debug(TAG, "Refreshed token: " + refreshedToken);
        SendRegistrationToServer(refreshedToken);
    }
    void SendRegistrationToServer(string token)
    {
    }
}
Initially I thought it has a different token but is the same.
Message from Azure Portal:
The token obtained from the token provider is wrong.
Android using Firebase Cloud Messaging not receiving message
As the GCM docs said :
An ID issued by the GCM connection servers to the client app that allows it to receive messages.
So only when the token is available, your app can receive message from GCM.
How can an app get that token?
You could see the document :
On initial startup of your app, the FCM SDK generates a registration token for the client app instance. If you want to target single devices or create device groups, you'll need to access this token.
The onTokenRefreshcallback fires whenever a new token is generated, so calling getToken in its context ensures that you are accessing a current, available registration token. Make sure you have added the service to your manifest, then call getToken in the context of onTokenRefresh
Every time when you re-run the application in your device the token is changed, but as the document said, OnTokenRefresh is only called when the system determines that the tokens need to be refreshed, it is needed for key rotation and to handle Instance ID changes due to :
When the app is installed or uninstalled.
When the user deletes app data.
When the app erases the Instance ID.
When the security of the token has been compromised.
You need to trigger OnTokenRefresh method. You should first uninstall the app from the device, then reinstall the app and open it, the OnTokenRefresh will be triggered and the token will be updated and your app could receive GCM message again.

GCM token refresh and when to send the token to server

I am following a GCM-Android integration example from the official guide.
In particular I am confused about the following lines in the above linked class:
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
Now I call the intent service each time my main activity launches and I believe that instanceID is responsible for initiating the token refresh.
Should I check the Shared Prefs value each time I initiate this GCM registration intent from my Main Activity. However refresh will fail in this case because after initial token fetch the condition will always be true.
Should I discard the shared prefs logic - this way a fresh token will be sent to my server each time. What is the proper way of doing this? How does the token refresh worrk and when does it refresh?
Yes, you don't need to save it in sharedPreference. To protect the client app and app server from potential malicious re-use of registration tokens, you should periodically initiate token refresh from the server. When GCM registration token refresh is initiated from server side, the client app must handle a tokenRefreshed message with the GCM registration client/server handshake.
Based on the document, backing up the registration token that Google Cloud Messaging registration returned can cause unexpected behavior in notifications for the restored app. This is because when a user installs your app on a new device, the app must query the GCM API for a new registration token. If the old registration is present, because the system had backed it up and restored it, the app doesn't seek the new token. To prevent this issue from arising, exclude the registration token from the set of backed-up files.
Here's a demo app for Google Services - MyInstanceIDListenerService: https://github.com/googlesamples/google-services/blob/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart/MyInstanceIDListenerService.java#L38
For more information, please read the Official Google Documentation here: https://developers.google.com/cloud-messaging/registration

InstanceID, what if I do not succeed on sending the token to my server?

I created a Push Notification Server (PNS) by using Google Cloud Messaging (GCM).
With this architecture, my server has to know the token associated to a user in order to send him push notifications.
I extended the class InstanceIDListenerService which is correctly notified when a token has been refreshed (I tested it with adb). When its method onTokenRefresh() is called I take the new token and, so far, all is ok.
My problem is the following: what if I fail to send this new token to my server? (a network error, a lack of connection, a sudden device shutdown, or something else...).
Do I have to store somewhere (preferences?) that server does not know my new token and retry when possible? Is there a way to let the OS to perform this operation?
You may use GCM NetworkManager to queue, schedule, check network connections and... , its very reliable and useful, it handles all of your desired tasks.
Also you have to save your token some where is your device, may be on your shared preferences, till you make sure your server recives it. Please note that if you want to use other features of GCM like topic messaging, you have to save and use token for all topic registrations.
Your app (when it runs) should always check if the token has been sent to the server. When onTokenRefresh is called you should generate and send a new token to the server. If sending the token to the server fails then the next time your app runs it should try again.
You are correct that if you fail to send the token to the server onTokenRefresh your app will not receive notifications till it is run again and successfully sends the token to the server.
Also note that token refresh should not be a regular occurrence. It should only happen for example when the app is uninstalled and reinstalled or the token is deemed to be no longer secure.

Categories

Resources