15

I have just migrated to FCM. I have added my class that extends from FirebaseInstanceIdService to receive a refreshedToken as and when appropriate.

My question is specific to the case when user installs my app first time and due to some reason, unable to receive a registration Id from onTokenRefresh. How are we supposed to handle this? Can I set a broadcast receiver from my FirebaseInstanceIdService class which will notify the Main activity when a registration Id is received?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Lucky
  • 151
  • 1
  • 1
  • 4
  • I think, `FirebaseInstanceId.getInstance().getToken()` will return null only when Internet is not available. – Chintan Soni May 30 '16 at 05:02
  • Yes, so how to handle this? – Lucky May 30 '16 at 05:04
  • So, just set `LocalBroadcastReceiver`. Send Broadcast from your method `onTokenRefresh()` and inside `MainActivity` catch that broadcast by setting BroadcastReceiver. – Chintan Soni May 30 '16 at 05:08
  • Thanks @ChintanSoni. I will try this! – Lucky May 30 '16 at 16:18
  • 1
    Looks like FCM not fully functional on devices like Xiaomi with Chinise OS version ( it comes without GooglePlay Services, but it still not fully functional even after installing GPServices) – Vitaliy A Sep 16 '16 at 10:43
  • @VitaliyA Same issue on Nexus 5x... NOT Chinise OS version.... -_- – Rahim Rahimov Nov 03 '16 at 22:57
  • @VitaliyA Same issue. Registration token is not fetched on Xiaomi phones, but it works on emulator,motorola and Samsung. Did you figure out something for this ? – Manisha Dec 01 '16 at 10:54
  • The only solution i found is to set SyanogemMOD ROM. https://www.youtube.com/watch?v=K-d-Bq_Ui5k – Vitaliy A Dec 01 '16 at 12:55
  • not called `onTokenRefresh` method on `YU` , ` Xiaomi` device with kitkat – Sagar Nov 21 '18 at 06:32

7 Answers7

18
  • if your device have no connection to the internet onTokenRefresh() is never called and you should notify to user his/her device has no internet connection
  • firebase has its own network change listener and when a device connected to the internet then try to get token and return it, at this time you can tell your main activity by sending a local broadcast receiver that registration token is received.

use below codes:

    @Override
public void onTokenRefresh() {

    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();

    Log.d("FCN TOKEN GET", "Refreshed token: " + refreshedToken);

    final Intent intent = new Intent("tokenReceiver");
    // You can also include some extra data.
    final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
    intent.putExtra("token",refreshedToken);
    broadcastManager.sendBroadcast(intent);


}

in your main activity:

    public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
   LocalBroadcastManager.getInstance(this).registerReceiver(tokenReceiver,
            new IntentFilter("tokenReceiver"));

}

BroadcastReceiver tokenReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String token = intent.getStringExtra("token");
        if(token != null)
        {
            //send token to your server or what you want to do
        }

    }
};

}
Crocodile
  • 5,724
  • 11
  • 41
  • 67
Edalat Feizi
  • 1,371
  • 20
  • 32
  • 2
    Hi, i'm wondering if you could explain what to do if there is no token. In my app there always has to be a token from the start. I was thinking it would go something like, `splashscreen -> if(noToken){ continue with splashscreen until token and then remove splashscreen for main activity }` any help would be greatly appreciated – Wisd0m Jun 17 '16 at 01:28
  • when your app is start FirebaseInstanceId service try to get token from FCM you can show a progress bar in splash screen until FirebaseInstanceId service return a token if FirebaseInstanceId return a token then send it to your app server and tell to your splash screen activity token is received with a LocalBroadcastManager then close splash screen and display your app main activity else tell to splash screen activity token cannot received and show a message to user you have no internet connection after user connect to internet FirebaseInstanceId service try to get token again – Edalat Feizi Jun 17 '16 at 14:56
  • Thank you for your response, I will try and implement that. One other thing if you could help me understand, my Android app is developed in PHP and is displayed as a webView. I can send the token to the server but how would I store the token on my PHP server to be used when the user registers so I can store the token and user_I'd in the database. Any help would be greatly appreciated as I have been stuck on this for the last 4days – Wisd0m Jun 17 '16 at 15:26
  • Beautiful, Thanks. – Alaa Jul 20 '17 at 09:10
  • @Alaa Glad to help you :) – Edalat Feizi Jul 22 '17 at 07:26
12

Change this in manifest.xml file tools:node="replace" to tools:node="merge".

Azeez
  • 171
  • 2
  • 9
6

As far as I know, token will be null only when you try to run your app on emulator on which google play service is not there and when you are using dual email id on you google play store(on you actual device), but only one email id is verified for the usage. Those are the cases which will give you null token and I have already implemented FCM in my new project. So for rest of any cases , token won't be null.

Mrugesh
  • 4,381
  • 8
  • 42
  • 84
  • token will be null until the application is able to obtain a valid token. The requirements for obtaining a token are: 1. google-play-services installed on the device and 2. device is connected to internet. Even if the requirements are met it's possible that the token will take some time (usually < 10 seconds) to be available. This depends on local conditions like network, device load etc.. – Diego Giorgini May 30 '16 at 20:00
  • if the delay is there, automatically `onTokenRefresh` method will be called and will get updated token and if internet is not there, then first of all handle `internet connectivity` in your app – Mrugesh May 31 '16 at 03:16
2

Use this class extends with..

public class MyFirebaseInstanceIDService  extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";
    public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";


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

        Toast.makeText(MyFirebaseInstanceIDService.this,refreshedToken,Toast.LENGTH_LONG).show();
    }
}
FelixSFD
  • 6,052
  • 10
  • 43
  • 117
Munna Sharma
  • 109
  • 1
  • 1
2

I was facing the same problem. I looked through a lot of SO posts and other forums and I found a solution that worked for me. FCM documentation says to use this method to get a token.

String refreshedToken = FirebaseInstanceId.getInstance().getToken();

I found a post online (I apologize, I don't remember which one. I found it a while ago) that used this method instead:

String refreshedToken = FirebaseInstanceId.getInstance().getToken() (String authorizedEntity, String scope);

FCM documentation describes the first method as:

Return the master token for the default Firebase project.

While the second one is described as:

Returns a token that authorizes an Entity to perform an action on behalf of the application identified by Instance ID. This is similar to an OAuth2 token except, it applies to the application instance instead of a user. For example, to get a token that can be used to send messages to an application via FirebaseMessaging, set to the sender ID, and set to "FCM".

I have been looking into why the first method call takes a longer time to return a token, but I haven't found an answer yet. Hope this helps.

Marline
  • 269
  • 3
  • 10
  • 4
    This should be a comment, not an answer. If it is a duplicate question, [vote to close](http://stackoverflow.com/help/privileges/close-questions) or [flag](http://stackoverflow.com/help/privileges/flag-posts) as such and/or leave a comment once you [earn](http://meta.stackoverflow.com/q/146472) enough [reputation](http://stackoverflow.com/help/whats-reputation). If not, tailor the answer to this specific question. – NobodyNada May 11 '17 at 21:17
  • @NobodyNada you could have just said that. no reason to down vote an answer that works. – Marline May 11 '17 at 21:22
  • 2
    Sorry, but this is not "an answer that works." See [Your answer is in another castle; when is an answer not an answer?](https://meta.stackexchange.com/q/225370/258777) – NobodyNada May 11 '17 at 21:49
  • I've raised a duplicate flag on the question. They do look like they're the same. In the meantime, suggest just deleting this answer and flagging as duplicate yourself; it's not adding value and is attracting negative attention. – Krease May 11 '17 at 22:09
  • 1
    @Krease I did not have enough reputation to flag the question as duplicate before or now after your down votes. I adjusted my answer to the best of my knowledge. I hope its in a format that is acceptable as an answer now. – Marline May 12 '17 at 00:56
  • I was getting token null always on my onTokenRefresh() in FirebaseInstanceIdService (first install, other launches, internet on/off etc). I tried everything and by changing to the overload that @Marline mentioned public String getToken (String authorizedEntity, String scope) now i can get the token. – Xaren Jun 07 '18 at 18:49
1

depending on your application logic you can write the code to handle the "new" token directly in the FirebaseInstanceIdService.onTokenRefresh() method, or you can use a LocalBroadcast to send this information to your activity if you need to change the UI when this event happens.

Note that when onTokenRefresh() is called your activity could be closed.

A possible implementation could a mix of the two options:

  1. add some logic in onTokenRefresh() to send the token to your server
  2. use a LocalBroadcastReceiver to inform your activity, if you have a piece of UI that need to change when the token is available.
Diego Giorgini
  • 12,489
  • 1
  • 47
  • 50
0

If you are running it on your emulator, check that you have Google play services enabled in Tools -> Android -> SDK Manager -> SDK Tools -> Google play services

Once installed, reboot both Android Studio and your emulator

It worked for me