73

In my MainActivityin my log, I can see the token using FirebaseInstanceId.getInstance().getToken() and it display the generated token. But it seems like in my MyFirebaseInstanceIDService where it is extends to FirebaseInstanceIdService, the onTokenRefresh() is not called, where in this function it was said that the token is initially generated here. I needed to call sendRegistrationToServer() that's why I'm trying to know why it doesn't go in the onTokenRefresh().

Here is my code

public class MyFirebaseInstanceIDService  extends FirebaseInstanceIdService {


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

        sendRegistrationToServer(refreshedToken);
    }
}
natsumiyu
  • 3,217
  • 7
  • 30
  • 54
  • Possible duplicate of [Firebase FCM force onTokenRefresh() to be called](http://stackoverflow.com/questions/37454501/firebase-fcm-force-ontokenrefresh-to-be-called) – Machado Aug 15 '16 at 20:39
  • 2
    Please read the questions completely. This question is not duplicate of the question you mentioned. @Machado – Wijay Sharma Mar 06 '18 at 18:24

13 Answers13

106

onTokenRefresh in FirebaseInstanceIdService is only called when a new token is generated. If your app was previously installed and generated a token then onTokenRefresh would not be called. Try uninstalling and reinstalling the app to force the generation of a new token, this would cause onTokenRefresh to be called.

Also be sure that your FirebaseInstanceIdService is properly defined in your AndroidManifest.xml

In your Manifest File.

 <service
        android:name="com.bnt.etailers.fcm.MyFireBaseInstanceIDService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

    <service
        android:name="com.bnt.etailers.fcm.GCMNotificationIntentService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

FirebaseInstanceIdService class

public class MyFireBaseInstanceIDService extends FirebaseInstanceIdService {


private static final String TAG = MyFireBaseInstanceIDService.class.getSimpleName();

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

    if (refreshedToken!=null) {
        SettingPreferences.setStringValueInPref(this, SettingPreferences.REG_ID, refreshedToken);
    }
    // TODO: Implement this method to send any registration to your app's servers.
    sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]

/**
 * Persist token to third-party servers.
 *
 * Modify this method to associate the user's FCM InstanceID token with any server-side account
 * maintained by your application.
 *
 * @param token The new token.
 */
private void sendRegistrationToServer(String token) {
    // Add custom implementation, as needed.
}}

FirebaseMessagingService class.

public class GCMNotificationIntentService extends FirebaseMessagingService {
// Sets an ID for the notification, so it can be updated


public GCMNotificationIntentService() {
    super();
}


@Override
public void onMessageReceived(RemoteMessage message) {

}}
Aritz
  • 30,971
  • 16
  • 136
  • 217
Sagar Gangawane
  • 1,985
  • 1
  • 12
  • 22
  • 1
    The documentation seems confusing(https://firebase.google.com/docs/cloud-messaging/android/client), it says The registration token may change when:The app deletes Instance ID, and if I manually call FirebaseInstanceId.getInstance().deleteInstanceId(); I was expecting a new token generated, but nothing actually happens in this case, onTokenRefresh is never called. – WenChao Aug 04 '16 at 03:46
  • 2
    Why save the token to shared preferences - if you can call [FirebaseInstanceId.getInstance().getToken()](https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId) at any time to get its value? – Alexander Farber May 29 '17 at 08:08
  • @WenChao make sure you call InstanceID of the playservice by `InstanceID.getInstance(this).deleteInstanceID()` and call it from background thread, after u successfully delete it, call `InstanceID.getInstance(this).getID()` to generate new token – Salis Jun 03 '17 at 06:20
  • @Alexander Farber, it's because you can only get the token once, you need to persist it to use it later. For example, I'm doing an app that does not need the user to be registered, but it he wants to subscribe to certain update, he can register, I can send the token of his device with his data, but if I would got the token when he first installed the app, that wouldn't be possible. – Sterling Diaz Nov 14 '17 at 17:58
  • I am testing it on `kitkat and above` devices on `kitkat` `onTokenRefresh` method is not triggering `FCM version 11.6.2` – Sagar Nov 21 '18 at 06:24
23

I had the same problem like you. My mistake was the following: I placed my <service> tags outside the <application> tag in the AndroidManifest.xml file.

Now mine looks like this:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <service
        android:name=".MyFirebaseMessagingService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

    <service
        android:name=".MyFirebaseInstanceIDService">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>
</application>

And it works without any problem.

viplezer
  • 5,519
  • 1
  • 18
  • 25
  • 1
    Credits goes to this thread: http://stackoverflow.com/questions/37351354/firebase-cloud-messaging-notification-not-received-by-device – viplezer May 26 '16 at 13:29
  • great answer...is this the facebook id that gets returned?.......cause I'm trying to do that and I'm getting a very large token – John Oct 15 '16 at 03:43
  • Facebook? Firebase? You get the token for Firebase Cloud Messaging in your FirebaseInstanceIDService subclass's onTokenRefresh method and yes, it is a long string, my token is 152 character long. – viplezer Oct 19 '16 at 20:57
  • this is the solution for me. – jet_choong Jul 29 '17 at 06:26
  • @viplezer on my `KITKAT` not able to get `token` above its working. please help – Sagar Nov 20 '18 at 10:51
17

Yes this might happen some times.

Please call the following method wherever you want to get your fcm id.

    try {
            String refreshedToken = FirebaseInstanceId.getInstance().getToken();
            Log.d("Firbase id login", "Refreshed token: " + refreshedToken);
        } catch (Exception e) {
            e.printStackTrace();
        }
Surendar D
  • 5,554
  • 4
  • 36
  • 38
14

Try re-install the app, by uninstall it first from your device or emulator. It will then generate a new token, thus onTokenRefresh() will be called again.

Faruk
  • 5,438
  • 3
  • 30
  • 46
13

In my case I forgot to add internet permission in manifest,

<uses-permission android:name="android.permission.INTERNET" />

Hope most people won't make this mistake.

Sreedhu Madhu
  • 2,480
  • 2
  • 30
  • 40
4
try {
    FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
    e.printStackTrace();
}

in onCreate method to delete token.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
pru
  • 41
  • 1
4

Reinstalling did the trick for me!

Sterling Diaz
  • 3,789
  • 2
  • 31
  • 35
4

Make sure you have added

apply plugin: 'com.google.gms.google-services'

this to bottom of the app.gradle file

user2837615
  • 296
  • 1
  • 5
  • 12
3

In my case, I tried everything but onTokenRefresh was never called. Then I change my WiFi and I connect to different network, Now it worked!!. Previous WiFi has good internet connectivity, Don't know why it was happening. May be this can help someone.

karanatwal.github.io
  • 3,613
  • 3
  • 25
  • 57
3

I have experienced that MyFirebaseInstanceIDService is not called when you are running your application on a device where internet connectivity is not available. In this way onTokenRefresh() is not called. So make sure that your device must has internet connection during running your application for taking updated FirebaseToken.

Also uninstall the previous app & Re-Install it for taking updated token. The registration token change when:

1) The app deletes Instance ID

2) The app is restored on a new device

3) The user uninstalls/reinstall the app

4) The user clears app data.

Sheharyar Ejaz
  • 2,808
  • 1
  • 14
  • 15
3

I've been struggling with that for over an hour, then I changed the following code and it suddenly worked.

handle your refreshedToken as such:

String refreshedToken;
    try {
        refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
        Localytics.setPushRegistrationId(refreshedToken);
    } catch (Exception e) {
        Log.d(TAG, "Refreshed token, catch: " + e.toString());
        e.printStackTrace();
    }

Try adding android:exported="true"> to both MyFirebaseMessagingService and MyFirebaseInstanceIDService in manifest so it looks like that:

<service
        android:name="com.localytics.android.sample.fcm.MyFirebaseMessagingService"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

    <service
        android:name="com.localytics.android.sample.fcm.MyFirebaseInstanceIDService"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>

Uninstall your app, Install again, worked. Tested on real device.

android:exported="true" is a default option so you can also remove that entirely and it will be set to true.

Also if you want to call onTokenRefresh more explicitly, you can simply call that anywhere in your code:

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

You don't have to rely on broadcast being received any more

psydj1
  • 181
  • 10
3

There are several reasons to not calling the onTokenRefresh methon not called. I have listed that and mention it one by one .

  1. Please make sure you have added the internet permission

  2. check have you added the google-services.json file that generate from google console inside of app directory in your project

enter image description here

  1. In your module Gradle file (usually the app/build.gradle), add the apply plugin line at the bottom of the file to enable the Gradle plugin:
apply plugin: 'com.android.application'

android {
  // ...
}

dependencies {
  // ...
  implementation 'com.google.firebase:firebase-core:16.0.4'

  // Getting a "Could not find" error? Make sure you have
  // added the Google maven respository to your root build.gradle
}

// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'

4) add the play service class path in project level build.gridle file

buildscript {
    // ...
    dependencies {
        // ...
        classpath 'com.google.gms:google-services:4.1.0' // google-services plugin
    }
}

allprojects {
    // ...
    repositories {
        // ...
        google() // Google's Maven repository
    }
}

5) Make sure you have added those service in the AndroidManifes file inside application tag

<service
    android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service> </application>

6) onToken refresh is called when token refresh and when install the app for the first so make sure you have deleted the app manually or clear the data

7) Make sure you have extends the FirebaseMessagingService in your service class

[Note : If its not working only for specific version for example android kitkat version then try to change the fcm version.]

Hoque MD Zahidul
  • 10,560
  • 2
  • 37
  • 40
2

I had the same problem. My device(kitkat 4.4.2) couldn't get onTokenRefresh() for some reason. My internet connection was perfect, google play services was up to date and all necessary contiditions for firebase to work were met. My code worked perfectly on the devices 5.0.0 and higher. To solve this issue i had to reset my device to factory settings and application started to work. I know it's tough measure but maybe it may help somebody. There must be some problems or conflict with other application, which caused onTokenRefresh() not to be called. Good luck!

Feras Al Sous
  • 1,073
  • 1
  • 12
  • 23