I am trying to implement notifications and can send a notification using the firebase console to all devices of the app, however I am having problem trying to retrieve the token of a device so i can send the notification to one particular device. I have a service that extends FirebaseMessagingService and includes the method onNewtoken seen below. I have added this service to my manifest and tried running the app but still unable to find the token. Is there something im doing wrong?
#Override
public void onNewToken(#NonNull String s) {
super.onNewToken(s);
Log.d("NEW_TOKEN",s);
}
OnNewtoken will trigger only by following below scenarios
The app deletes Instance ID
The app is restored on a new device
The user uninstalls/reinstalls the app The user clears app data.
you can get user token by below code as well
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String token = instanceIdResult.getToken();
// send it to server
}
});
You can get token forcefully like this u can call this code from onCreate() as sometimes when app has already generated to token it does not call onNewToken
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
KLog.w("getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
if (task.getResult() != null) {
String token = task.getResult().getToken();
}
}
});
Related
I am using Firebase FCM to send notifications from my server to the users.
When the user installs the App for the first time, i catch the fresh and new token at MessagingService.java:
#Override
public void onNewToken(#NonNull String tkn) {
super.onNewToken(tkn);
sendTokenToServer(tkn);
}
Here comes the problem, when the user closes session (without uninstalling the app), SharedPreferences are deleted. A new session is started; but onNewToken() is not called. So, i must manually retrieve the Token inside my MainActivity in order to send it to the server. I am getting the updated token with this piece of code:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(MainActivity.this, new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
sendTokenToServer(instanceIdResult.getToken());
}
});
As you know, that code is deprecated and should be avoided. Instead, i tried to replace it with this piece of code with no success:
FirebaseInstallations.getInstance().getToken(true).addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
#Override
public void onComplete(#NonNull Task<InstallationTokenResult> task) {
if(task.isSuccessful()) {
String token = task.getResult().getToken();
}
}
});
The Token length obtained at onNewToken() is 163.
The token length obtained at deprecated call is 163 (perfect, but deprtecated).
The token length obtained at FirebaseInstallations is 316.
My firebase API at server side fails to send a notification using the code of 316 length.
Any one knows what i am doing wrong? Or why i get those different length tokens?
Update:
Server side python, retrieves token from database and sends the notification like this. Please note this code is working when token len is 163.
from pyfcm import FCMNotification
push_service = FCMNotification(api_key=" ... ")
push_service.notify_single_device(registration_id=token, data_message=datamessage, time_to_live=1296000)
When trying to send a notification with long token this is the message I get:
{'multicast_ids': [8149274412512777031], 'success': 0, 'failure': 1, 'canonical_ids': 0, 'results': [{'error': 'InvalidRegistration'}], 'topic_message_id': None}
From the documentation for FirebaseInstanceId:
This class is deprecated. Firebase Instance ID has been replaced with
FirebaseInstallations for app instance identifiers and
FirebaseMessaging.getToken() for FCM registration tokens.
Looks like you need FirebaseMessaging.getToken() not FirebaseInstallations.getInstance().getToken(true) as you want a FCM registration token.
These APIs provide different tokens for different purposes.
So in your example it would be:
FirebaseMessaging.getInstance()
.getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override public void onComplete(#NonNull Task<String> token) {
}
}
);
As we know we can get firebase token on onNewToken(...) in our class inherited of FirebaseMessagingService. But I have a question, that method will not call on update app case, and if I already have a token before, but I didn't save it. How to get it??
Example: In my class inherit from FirebaseMessagingService
class CustomFirebaseService : FirebaseMessagingService() {
override fun onNewToken(newToken: String) {
supper.onNewToken(newToken)
// I have token in here, but I already didn't save it on any where (sharedperf, db,..)
}
And now in my application, I need to use it, but I don't sure what the best way to get it??
class App: Application() {
override fun onCreate() {
super.onCreate()
// I need to use token here, but method onNewToken will not called, because the current token is valid.
}
}
Maybe, Can I use FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(..)? Do it duplicate with my custom service??
As the Firebase documentation on getting the current registration token says:
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();
// 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();
}
});
You typically only need this in development, as the initial token is typically generated before you have an onNewToken. Once your app is in production, the onNewToken code will be called from the moment the first token is generated.
I have integrated firebase as a backend in my android app.I am trying to change users device id every time app opens.
I am using below code to get firebase registration id:
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 Instance ID token
String token = task.getResult().getToken();
Toast.makeText(MainActivity.this, token, Toast.LENGTH_SHORT).show();
}
});
How can I change this token every time users open an app.
Any help would be appreciated.
THANKS
The registration token may change 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.
Read the documentation here
You can revoke the token from server and notify the device.
The procedure is well explained here.
I am learning to implement firebase in an android studio. And I have studied various tutorials on this subject.
So in order to minimize the chances of making mistakes, I decided to implement a simple token generated scripts in my mainactivity inside the onCreate() method; these codes below:
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;
}
String token = task.getResult().getToken();
}
});
Then the app keeps crashing after generating its apk.
Then following codes were then implemented:
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( MainActivity.this, new OnSuccessListener<InstanceIdResult>() {
#Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
}
});
I am using latest dependency :
firebase messaging:17.6.0
firebase-core:16.0.8
The problem is each time I generated the APK , the app keeps crashing with error message "app has stopped".
But when I built any other android app without firebase ,the app will work perfectly.
How to check this condition and then send to server when refresh token?
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
Here is my code to send server. But is it send all time when app login ? How to send when above condition?
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.e("NEW_TOKEN", s);
sendRegistrationToServer(s);
}
private void sendRegistrationToServer(String token) {
APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
Call<Fcm> call = apiInterface.postFCMToken(user_id, newToken);
call.enqueue(new Callback<Fcm>() {
#Override
public void onResponse(Call<Fcm> call, Response<Fcm> response) {
}
#Override
public void onFailure(Call<Fcm> call, Throwable t) {
}
});
}
In general, you should expect that an app installation is unable to reliably detect when an FCM token changes. As such, any new token should be unconditionally reported to the backend, as a potential target for messaging for the given user.
The server side of your app can remove invalid tokens by looking at the error response when attempting to send a message to a token that's no longer valid. If you're using the Admin SDK to send a message to a device token, you can detect then when a token is invalid because the API will generate the error messaging/registration-token-not-registered, according to the documentation.