33

I was trying to get the FCM working in my app in the past few days, and I saw that the onTokenRefreshed() function and FirebaseInstanceIdService in general, is deprecated. So I followed some firebase documentations and tutorials online, but none of them seemed to be working for me. My MyFirebaseMessagingService class is:

package com.example.android.aln4.Classes;

import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMessaging";

    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        Log.d(TAG,"Refreshed token: "+token);
    }
}

and my manifest contains this following code:

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

Plus, all of my firebae-related implemetations are up-to-date, as the following:

  //Firebase
    implementation 'com.google.firebase:firebase-crash:16.2.1'
    implementation 'com.firebase:firebase-client-android:2.5.2'
    implementation 'com.google.firebase:firebase-core:16.0.6'
    implementation 'com.google.firebase:firebase-database:16.0.6'
    implementation 'com.firebase:firebase-client-android:2.5.2'
    implementation 'com.firebaseui:firebase-ui-database:2.1.1'
    implementation 'com.google.firebase:firebase-storage:16.0.5'
    implementation 'com.google.firebase:firebase-firestore:18.0.0'
    implementation 'com.google.firebase:firebase-messaging:17.3.4'

My problem in general, is that whenever I run the app, doesn't matter if it's after uninstalling and installing or on a regular run, the onNewToken() function is not called, or at least I don't see it in the Logcat. Any sort of help would be appriciated :)

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Adi Harel
  • 505
  • 1
  • 5
  • 10
  • 4
    That's ok, it doesn't have to be called. If it does not - you can get the current token. – Vladyslav Matviienko Feb 01 '19 at 08:15
  • Read this https://stackoverflow.com/a/51835126/7666442 – AskNilesh Feb 01 '19 at 08:21
  • @VladyslavMatviienko yeah, I forgot to mention, the onMessageRecieved doesn't work (or isn't called) either – Adi Harel Feb 01 '19 at 08:22
  • then *probably* you are sending the message to the wrong token. Or maybe something else. You have to check everything, nobody can do it instead of you – Vladyslav Matviienko Feb 01 '19 at 08:23
  • @VladyslavMatviienko I just learnt about the whole process a few days ago, how to I do that? How do i get the right token? – Adi Harel Feb 01 '19 at 08:24
  • Show how you are getting the token first – Vladyslav Matviienko Feb 01 '19 at 08:27
  • @VladyslavMatviienko im using the FirebaseInstanceId.getInstance().getInstanceId() method, getting the task from it, and saving it to a string like that: String token=task,getResult().getToken(); – Adi Harel Feb 01 '19 at 08:36
  • have you checked with a debugger, or whatever if it returns you the token? – Vladyslav Matviienko Feb 01 '19 at 08:37
  • @VladyslavMatviienko yes, it crashes every time it gets to that function – Adi Harel Feb 01 '19 at 08:44
  • that is obviously the problem. – Vladyslav Matviienko Feb 01 '19 at 08:49
  • @VladyslavMatviienko nevermind, got it, its getting the token now. but the problem is that i still don't understand why i cant get the message – Adi Harel Feb 01 '19 at 08:50
  • are you sure that you send the message to the right token? Have you sent the right to ken to the server, etc... – Vladyslav Matviienko Feb 01 '19 at 08:51
  • Try to add `FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener` in activity, and check what will be returned from that task. – grabarz121 Feb 01 '19 at 08:53
  • @VladyslavMatviienko I'm afraid you didn't understand me... But hold on to that, do I need to save the token to each user differently in the firebase database? if so, how do I send it to each one? Because from what I understand, i need to go to firebase notifications and send a notification manually.... – Adi Harel Feb 01 '19 at 08:55
  • @grabarz121 Yeah I already added this and it worked, check the 7th comment here :) – Adi Harel Feb 01 '19 at 08:55
  • you can send them manually, or using the API. I never sent manually, therefore I have no idea how to do that, but you likely have to identify the device to send it to somehow – Vladyslav Matviienko Feb 01 '19 at 08:59
  • @VladyslavMatviienko I want to do that using the API, I didn't know this opportunity is possible, if you could share a link to guide me through using this API I'd love that. Back to the topic, do I need to save the token to the user in the database every time it logs in? – Adi Harel Feb 01 '19 at 09:06
  • @VladyslavMatviienkoV are you still there...? – Adi Harel Feb 01 '19 at 19:52
  • 1
    @AdiHarel Did you able to resolve this issue, we are facing exact same issue and unable to find a fix for this since 2 days. Can you please let us know the solution, if your are able to resolve. Any help would be appreciated.. – Rohit Rathore Sep 20 '19 at 11:30

7 Answers7

25

onNewToken method is just called when the token is generated, you should retrieve the token in an activity.

Add this to your activity:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(SplashActivity.this, new OnSuccessListener<InstanceIdResult>() {
        @Override
        public void onSuccess(InstanceIdResult instanceIdResult) {
            String token = instanceIdResult.getToken();
            Log.i("FCM Token", token);
            saveToken(token);
        }
    });
Helton Malambane
  • 1,147
  • 11
  • 12
  • Thank you! So this method is now also deprecated as well. Do you happen to know what is the currently accepted method to access this now? It seems like google depricates these methods as fast as it creates them. – Terry Jan 29 '21 at 23:00
  • onNewToken called when a new token for the default Firebase project is generated. This is invoked after app install when a token is first generated, and again if the token changes. https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService#public-void-onnewtoken-string-token – Yohanim Mar 24 '21 at 08:43
13

December 2020 update : Using the new Firebase SDK (21.0.0) , you can get the token by FirebaseInstallations.getInstance() within your scope :

FirebaseInstallations.getInstance().getToken(false).addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
          @Override
          public void onComplete(@NonNull Task<InstallationTokenResult> task) {
              if(!task.isSuccessful()){
                  return;
              }
              // Get new Instance ID token
              String token = task.getResult().getToken();

          }
      });

EDIT : December 2022 update : Using new Firebase SDK (23.1.0) :

   FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
          @Override
          public void onComplete(@NonNull Task<String> task) {
              if(!task.isSuccessful()){
                  return;
              }
              // Get new Instance ID token
              String token = task.getResult();
             
          }
      });
ismail alaoui
  • 5,748
  • 2
  • 21
  • 38
  • So why do most of the examples just have getInstanceId() then add a listener there - this is not a method in my version of the SDK perhaps? The other examples that do getToken().addOnCompleteListener, appear to be there.. But the other examples are listed with confidence? Mobile development is starting to look like "google your brains out until you have an app". For example, I couldn't find anything that mentioned getNotification for days, then I saw it while hovering in the tooltip or it still wouldn't work. Any secrets? – Dan Chase Jun 27 '23 at 15:04
4

USE this :

FirebaseMessaging.getInstance().setAutoInitEnabled(true);
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Yamini
  • 732
  • 7
  • 11
4

onNewToken() will be called only when there is a new token generated or existing token updated.

You can add the following code and call wherever you want in the app to fetch the token anytime.

    FirebaseInstanceId.getInstance().getInstanceId()
    .addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
        @Override
        public void onComplete(@NonNull Task<InstanceIdResult> task) {
            if (!task.isSuccessful()) {
                Log.w(TAG, "getInstanceId failed", task.getException());
                return;
            }

            // Get new Instance ID token
            String token = task.getResult().getToken();


        }
    });
rajkabbur
  • 187
  • 3
4

After connecting your app to FCM by using firebase assistant tool of android studio, use this code on your MainAcitivity class to retrieve firebase cloud messaging token : (This code works for me)

FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                Toast.makeText(this, "${task.exception}", Toast.LENGTH_LONG).show()
                return@OnCompleteListener
            }

            // Get FCM registration token
            val token = task.result
            if (token != null) {
                Toast.makeText(this, token, Toast.LENGTH_LONG).show()
            }
        })
Biplob Das
  • 2,818
  • 21
  • 13
1

Receive a token like this (Kotlin):

FirebaseMessaging.getInstance().token.result?.let{ Log.e(TAG, "onCreate: $it")}
Falchio
  • 174
  • 1
  • 14
-1

You only need onNewToken() to signal your app that it needs to send the token again.

You could do this at some entry point of your app:

private void doPushCheck() throws ExecutionException, InterruptedException {
    if (isPushTokenAlreadySent()) {
        return;
    }
    Task<InstanceIdResult> instanceId = FirebaseInstanceId.getInstance().getInstanceId();
    Tasks.await(instanceId);
    InstanceIdResult result = instanceId.getResult();
    if (result != null) {
        String sPushToken = result.getToken();
        if (!TextUtils.isEmpty(sPushToken)) {
            [send token to your backend and verify your server response]
            setPushTokenSent(true);
        }
    }
}

On your on onNewToken() method override, you could simply do this:

@Override
public void onNewToken(@NonNull String sPushToken) {
    setPushTokenSent(false);
}

Methods isPushTokenAlreadySent() and setPushTokenSent() could be your favourite way of persisting data, for example with SharedPreferences:

private boolean isPushTokenAlreadySent() {
    SharedPreferences preferences = getApplicationContext().getSharedPreferences("push_token", Context.MODE_PRIVATE);
    return preferences.getBoolean("registered", false);
}

private void setPushTokenSent(boolean bSent) {
    SharedPreferences preferences = getApplicationContext().getSharedPreferences("push_token", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = preferences.edit();
    preferences.getBoolean("registered", bSent);
    editor.apply();
}
Reaper
  • 486
  • 3
  • 12