Firebase (FCM) how to get token
AndroidFirebaseFirebase Cloud-MessagingAndroid Problem Overview
It's my first time using FCM.
I download a sample from firebase/quickstart-android and I install the FCM Quickstart. But I can't get any token from the log even hit the LOG TOKEN button in the app.
Then I try to send a message with Firebase console and set to target my app package name. I got incoming messages.
I want to know can FCM be used?GCM everything is ok.
Solution:
Because I am not an Android developer, just a backend developer. So it takes me some time to solve it. In my opinion, there`re some bugs in the sample app.
Code:
RegistrationIntentService.java
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
public RegistrationIntentService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
String token = FirebaseInstanceId.getInstance().getToken();
Log.i(TAG, "FCM Registration Token: " + token);
}
}
MyFirebaseInstanceIDService.java
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
// String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Log.d(TAG, "Refreshed token: " + refreshedToken);
//
// // TODO: Implement this method to send any registration to your app's servers.
// sendRegistrationToServer(refreshedToken);
//
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
// [END refresh_token]
/**
* Persist token to third-party servers.
* <p>
* 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.
}
}
Add this in the MainActivity.java.
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
After do above,you get the Token in Logcat. But finally, I find a convenient way to get it.Just use debug mode to install the sample app and you can get the token when you first time to install it.
But I don't know why it can't print the log when I install it. Maybe be related to the mobile system.
And then why I can't get the Notification. FirebaseMessagingService.onMessageReceived did not call sendNotification
Android Solutions
Solution 1 - Android
FASTEST AND GOOD FOR PROTOTYPE
The quick solution is to store it in sharedPrefs and add this logic to onCreate
method in your MainActivity or class which is extending Application.
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
String newToken = instanceIdResult.getToken();
Log.e("newToken", newToken);
getActivity().getPreferences(Context.MODE_PRIVATE).edit().putString("fb", newToken).apply();
});
Log.d("newToken", getActivity().getPreferences(Context.MODE_PRIVATE).getString("fb", "empty :("));
CLEANER WAY
A better option is to create a service and keep inside a similar logic. Firstly create new Service
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("newToken", s);
getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
}
public static String getToken(Context context) {
return context.getSharedPreferences("_", MODE_PRIVATE).getString("fb", "empty");
}
}
And then add it to AndroidManifest file
<service
android:name=".MyFirebaseMessagingService"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Finally, you are able to use a static method from your Service MyFirebaseMessagingService.getToken(Context);
THE FASTEST BUT DEPRECATED
Log.d("Firebase", "token "+ FirebaseInstanceId.getInstance().getToken());
It's still working when you are using older firebase library than version 17.x.x
Solution 2 - Android
Complete Solution:
The team behind Firebase Android SDK change API a little bit. I've implemented "Token to Server" logic like this:
In my instance of FirebaseMessagingService:
public class FirebaseCloudMessagingService extends FirebaseMessagingService {
...
@Override
public void onNewToken(String token) {
// sending token to server here
}
...
}
Keep in mind that token is per device, and it can be updated by Firebase regardless of your login logic. So, if you have Login and Logout functionality, you have to consider extra cases:
- When a new user logs in, you need to bind token to the new user (send it to the server). Because token might be updated during the session of old user and server doesn't know token of the new user.
- When the user logs out, you need to unbind token. Because user should not receive notifications/messages anymore.
Using new API, you can get token like this:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String token = instanceIdResult.getToken();
// send it to server
}
});
Good luck!
Solution 3 - Android
FirebaseInstanceId
class and it's method getInstanceId
are also deprecated. So you have to use FirebaseMessaging
class and it's getToken
method instead.
FirebaseMessaging.getInstance().getToken().addOnSuccessListener(token -> {
if (!TextUtils.isEmpty(token)) {
Log.d(TAG, "retrieve token successful : " + token);
} else{
Log.w(TAG, "token should not be null...");
}
}).addOnFailureListener(e -> {
//handle e
}).addOnCanceledListener(() -> {
//handle cancel
}).addOnCompleteListener(task -> Log.v(TAG, "This is the token : " + task.getResult()));
The method getToken()
is deprecated. You can use getInstanceId()
instead.
If you want to handle results when requesting instanceId(token)
, check this code.
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
if (instanceIdResult != null) {
String token = instanceIdResult.getToken();
if (!TextUtils.isEmpty(token)) {
Log.d(TAG, "retrieve token successful : " + token);
}
} else{
Log.w(TAG, "instanceIdResult should not be null..");
}
}).addOnFailureListener(e -> {
//do something with e
}).addOnCanceledListener(() -> {
//request has canceled
}).addOnCompleteListener(task -> Log.v(TAG, "task result : " + task.getResult().getToken()));
Solution 4 - Android
Important information.
>if google play service hung or not running,
then fcm return token = null
If play service working properly then FirebaseInstanceId.getInstance().getToken()
method returns token
Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());
Solution 5 - Android
According to doc
Migrate a GCM client app to FCM
onTokenRefresh()
> only Called if InstanceID token is updated
So it will call only at first time when you install an app to your device.
So I suggest please uninstall your app manually and try to run again
definitely you will get TOKEN
Solution 6 - Android
Try this. Why are you using RegistrationIntentService
?
public class FirebaseInstanceIDService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
registerToken(token);
}
private void registerToken(String token) {
}
}
Solution 7 - Android
This line should get you the firebase FCM token.
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("MYTAG", "This is your Firebase token" + token);
Do Log.d to print it out to the android monitor.
Solution 8 - Android
If you are using above 'com.google.firebase:firebase-messaging:22.0.0'
Get FCM Token (Force) with Kotlin way:
FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String> ->
if (!task.isSuccessful) {
return@addOnCompleteListener
}
pushToken = task.result
Log.i("PUSH_TOKEN", "pushToken: $pushToken")
}
And you can get token via onNewToken method. (This class must be implemented)
class PushNotificationService: FirebaseMessagingService() {
override fun onNewToken(token: String) {
Log.e("PUSH_TOKEN", "Refreshed firebase token: $token")
}
}
You need add PushNotificationService to AndroidManifest.xml
<service
android:name=".PushNotificationService"
android:exported="false"
tools:ignore="Instantiatable">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Solution 9 - Android
Instead of this:
// [START refresh_token]
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
// String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Log.d(TAG, "Refreshed token: " + refreshedToken);
//
// TODO: Implement this method to send any registration to your app's servers.
// sendRegistrationToServer(refreshedToken);
//
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
// [END refresh_token]
Do this:
// [START refresh_token]
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Log.d(TAG, "Refreshed token: " + refreshedToken);
// Implement this method to send token to your app's server
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]
And one more thing:
> You need to call sendRegistrationToServer()
method
> which will update token on server, if you are sending push
> notifications from server.
UPDATE:
New Firebase token is generated (onTokenRefresh()
is called) when:
- The app deletes Instance ID
- The app is restored on a new device
- The user uninstalls/reinstall the app
- The user clears app data.
Solution 10 - Android
At the same time don not forget to include this in your manifest file to receive token id
<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
Solution 11 - Android
The FirebaseInstanceId.getInstance().getInstanceId()
is deprecated. Based on firebase document, you can retrieve the current registration token using following code:
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
// Log and toast
String msg = getString(R.string.msg_token_fmt, token);
Log.d(TAG, msg);
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
Solution 12 - Android
>UPDATE 11-12-2020
When you use 'com.google.firebase:firebase-messaging:21.0.0'
is FirebaseInstanceId
is depreacted now
Now we need to use FirebaseInstallations.getInstance().getToken()
and FirebaseMessaging.getInstance().token
SAMPLE CODE
FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener {
firebaseToken = it.result!!.token
}
// OR
FirebaseMessaging.getInstance().token.addOnCompleteListener {
if(it.isComplete){
firebaseToken = it.result.toString()
Util.printLog(firebaseToken)
}
}
Solution 13 - Android
You can use this method to get device token with firebase
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
String deviceToken = task.getResult();
}
});
Solution 14 - Android
In firebase-messaging:17.1.0
and newer the FirebaseInstanceIdService is deprecated, you can get the onNewToken
on the FirebaseMessagingService
class as explained on https://stackoverflow.com/a/51475096/1351469
But if you want to just get the token any time, then now you can do it like this:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(), new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
Log.e("newToken",newToken);
}
});
Solution 15 - Android
If are using some auth function of firebase, you can take token using this:
//------GET USER TOKEN-------
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
String idToken = task.getResult().getToken();
// ...
}
}
});
Work well if user are logged. getCurrentUser()
Solution 16 - Android
This the latest code to get fcm token in Activity (2021).
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
Log.d(TAG, "fcm token : "+token);
}
});
For new Token just add the newToken Method in FirebaseMessagingService extended class.
@Override
public void onNewToken(String token) {
super.onNewToken(token);
Log.d(TAG, token);
}
Solution 17 - Android
If you are using kotlin and co-routine then add kotlin coroutine play library
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:x.x.x'
use this simple method:
FirebaseMessaging.getInstance().token.await()
Solution 18 - Android
try this
FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(OnSuccessListener<InstanceIdResult> { instanceIdResult ->
fcm_token = instanceIdResult.token}
Solution 19 - Android
for those who land here, up to now FirebaseInstanceIdService
is deprecated now, use instead:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(String token) {
Log.d("MY_TOKEN", "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
// sendRegistrationToServer(token);
}
}
and declare in AndroidManifest
<application... >
<service android:name=".fcm.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
Solution 20 - Android
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();
}
});
Solution 21 - Android
Example to get firebase token inside suspend function
override suspend fun sendTokenToServer() {
try {
val token = FirebaseMessaging.getInstance().token.await()
Log.i("TAG", "token " + token)
} catch (exception:Exception) {
}
}
Solution 22 - Android
I'll make this short. This is the only non-deprecated way to retrieve the Firebase's token:
FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener(task -> {
// get token
String token = task.getResult().getToken();
})
Solution 23 - Android
Use below code for latest firebase version - 'com.google.firebase:firebase-messaging:22.0.0'
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
//handle token error
return;
}
strAppToken = task.getResult();
});
Solution 24 - Android
You can use the following in Firebase (FCM) to get the token:
FirebaseInstanceId.getInstance().getToken();
Solution 25 - Android
FirebaseInstanceId.getInstance().getInstanceId() deprecated. Now get user FCM token
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
System.out.println("--------------------------");
System.out.println(" " + task.getException());
System.out.println("--------------------------");
return;
}
// Get new FCM registration token
String token = task.getResult();
// Log
String msg = "GET TOKEN " + token;
System.out.println("--------------------------");
System.out.println(" " + msg);
System.out.println("--------------------------");
}
});
Solution 26 - Android
Flutter solution:
var token = await FirebaseMessaging.instance.getToken();
Solution 27 - Android
Settings.Secure.getString(getContentResolver(),
Settings.Secure.ANDROID_ID);