Firebase FCM token - When to send to server?

Okay so I have an app which on first start takes you through a few welcoming slides, then takes you to a login/register page and then to MainActivity.

I have just implemented FCM and the services generate a token before any of those pages have been seen by the user. How could I make it so that the service runs after I get to MainActivity?

The problem is I'm trying to send the token as soon as it is refreshed to the MySQL DB to the appropriate user account, but since the user hasn't signed in yet, that is null and my message to the server fails. What's a good way to design this? I thought of saving the token in SharedPreferences and sending it to the server after the user has logged in but that creates lots of complications when the token is refreshed at some later point?!

Possible solution:

I'm not sure I completely understand how the 2 services run but say in onTokenRefresh I just save the token into SharedPreferences and in MainActivity I get the value from SP and then I send it to the server. In that case when the token is refreshed the new value will immediately go into SharedPreferences again. But I would still need to check if it's a new value in SP and then reupload it to the server. This is confusing!


ANSWERS:


Yes FCM token is generated automatically. But try to see this in a different angle.

This is how I handled it.

Let FCM generate token as soon as your app starts. OnTokenRefresh will be called and you just save it in your preferences as:

@Override
public void onTokenRefresh() {
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    Log.d(TAG, "Refreshed token: " + refreshedToken);

    sendRegistrationToServer(refreshedToken);
}

private void sendRegistrationToServer(String token) {
    // Add custom implementation, as needed.
    SharedPreferenceUtils.getInstance(this).setValue(getString(R.string.firebase_cloud_messaging_token), token);

   // To implement: Only if user is registered, i.e. UserId is available in preference, update token on server.
   int userId = SharedPreferenceUtils.getInstance(this).getIntValue(getString(R.string.user_id), 0);
   if(userId != 0){
       // Implement code to update registration token to server
   }
}

Hope you are clear with the way. Ask if you need more clearance on it.


Note that you can always retrieve the token with:

FirebaseInstanceID.getInstance().getToken();

This will return null if the token has not yet been generated or the token if it has been generated. In your case it is very likely that the token will be generated by the time the user has signed in. So you should be able to send it to your app server as soon as the user has signed in. If it is not available then you would send it in the onTokenRefresh callback as Chintan Soni mentioned.


We handled it like this:

  1. Our server create/update the token value against a user id (primary key)
  2. Use 2 SharedPreferences
    1. String - token String
    2. Boolean (updated) - whether token is updated on server or not.

In case of token refresh we update the token string and set the boolean to false. Later whenever user login each time we check for boolean (updated), if that is false - we attach the current token to his id and send it to server and set updated to true.



 MORE:


 ? FCM - onTokenRefresh() is never called
 ? onTokenRefresh not getting called in signed APK, if previous version of app installed doesn't have FCM implemented
 ? FCM onTokenRefresh() sometimes not called
 ? FCM onTokenRefresh() Can't create handler inside thread that has not called Looper.prepare()
 ? Firebase FCM notifications click_action payload
 ? Firebase FCM notifications click_action payload
 ? Firebase FCM notifications click_action payload
 ? Firebase console: How to specify click_action for notifications
 ? open a specific activity from firebase notification
 ? FCM launcher activity not always opened