I´m trying to use FCM to send Firebase Notifications, but I have a Application using one Firebase Project and a library using another Firebase Project. I want to receive the token from library Firebase Project to receive Firebase Notifications.
When I try directly receive the token using:
FirebaseInstanceId.getInstance().getToken();
I received a valid token, but from Application Firebase Project. If i try to force in getInstance() the library Firebase Project, using:
FirebaseInstanceId.getInstance(FirebaseApp.getInstance("ABC")).getToken();
I receive null. If I try to use Application or Library Firebase Project passing parameters in getToken() as:
FirebaseInstanceId.getInstance().getToken(getApplication().getResources().getString(R.string.gcm_defaultSenderId), FirebaseMessaging.INSTANCE_ID_SCOPE);
or
FirebaseInstanceId.getInstance(FirebaseApp.getInstance("ABC")).getToken(getApplication().getResources().getString(R.string.gcm_defaultSenderId), FirebaseMessaging.INSTANCE_ID_SCOPE);
I received the same valid token from Application Firebase Project.
the R.string.gcm_defaultSenderId is from library project resources
There is another way to receive Library Firebase Project token or I'm doing something wrong?
This is my understanding of what you are observing based on my experiments and the documentation.
When you first call getToken() using a FirebaseApp other then the default, there is no token and communication with the server is required to produce one. A null value is returned and the process to fetch a token is initiated. The documentation for getToken() says it returns "the master token or null if the token is not yet available". After a few seconds the token is received. You can detect that event using the onTokenRefresh() method of FirebaseInstanceIdService, if you have implemented that. On subsequent calls to getToken() for the non-default app, the token will be present and returned immediately by getToken().
I think the calls to get a scoped token always return a token because they are blocking (see docs), and wait for the interaction with the server to complete before returning a result.
I made a mistake in FirebaseApp.initializeApp(), because I forgot to set:
.setGcmSenderId(getApplication().getResources().getString(R.string.gcm_defaultSenderId))
in FirebaseOptions.Builder().
After that change, I receive a valid Library Firebase Token in getToken() and in onTokenRefresh()
Related
My application is receiving the push notification from 2 firebase project. I am getting the tokens for each sender id by calling "getToken(String authorizedEntity, String scope)" separately.
String token1 = FirebaseInstanceId.getInstance().getToken("authorizedEntity1", "FCM");
String token2 = FirebaseInstanceId.getInstance().getToken("authorizedEntity2", "FCM");
As per the onTokenRefresh documentation
Called when the system determines that the tokens need to be refreshed. The application should call getToken() and send the tokens to all application servers.This will not be called very frequently, it is needed for key rotation and to handle Instance ID changes due to:
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
As onTokenRefresh has been deprecated, I have checked the onNewToken, As per the documentation
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.
Q1. How to know which is the default Firebase project in case of multiple sender id ?
Q2. Suppose if "authorizedEntity1" is associated with the default firebase project then does it mean onNewToken will be invoked only when token1 will be changed ? or it will be also invoked when token2 will be changed? If it doesn't work for token2 then how to know that token2 need to be refreshed?
Q3. With reference of this my understanding is onTokenRefresh will be invoked whenever any of the token needs to be refreshed(not only for default project). Is this understanding correct ?
I want to send the updated token to the server whenever system determines that the token1 or token2 need to be refreshed.
Note: I am initializing the firebase in my application class as I am dealing with multiple sender ids.
After some test, I found out that only default project's token will be delivered to onNewToken. onNewToken will not be called when new token created for other sender ids by calling getToken.
Tokens retrieved by calling getToken API are consist of different string data than default token.
And these other sender id's tokens are not refreshed when default token changes.
It look like they last until you explicitly call deleteToken API.
(Token value didn't changed when I repeatedly call getToken.)
Depending on #sNash comment who contaced Firebase Support, you should manage tokens for all sender ids other than the default sender id.
How?
One simple solution is through storing all sender ids with their tokens in SharedPreferences or in db. When app starts, check if the token changed for each sender by comparing the stored token with the token returned by
FirebaseInstanceId.getInstance().getToken(SENDER_ID, "FCM");
Moreover, do the same check in onNewToken method. There is a chance that tokens other than the default may be changed when the default token is changed.
The default sender is the one related to your Firebase project that the app is connected to and it can be found in google-services.json
I’m implementing Firebase Cloud Messaging (FCM) and am experiencing a problem that I’m unable to solve. I have implemented FirebaseMessagingService and FirebaseInstanceIdService according to the guide(s). When I go to Firebase Console for my app, and use the Notification function, I can successfully send a message to ALL my app instances (using the package name).
Now, in the code I have fetched the Firebase Instance Id (token) by use of the following code:
String token = FirebaseInstanceId.getInstance().getToken();
SendFirebaseTokenToServer(token);
(note that currently I’m using HTTP protocol, as my server does not yet have a cert). Anyway using the token I get from the call above, I go back to the Firebase Console and try to send a message to one (1) installed instance of my app. I grab the token from our server DB where it is stored as "varchar(max)". When I do that I get the following error message:
Invalid registration token. Check the token format.
I have googled that and found only one hit (having to do with Firebase and iOS):
http://stackoverflow.com/questions/41343520/ios-invalid-registration-token-check-the-token-format
That issue indicates that a cert was required (I think I’m reading it correctly). I’m not sure what I’m doing wrong. I need to get this to work using the Firebase Console first, then my server guy can start on his end knowing that it should work.
Turns out i was programatically encoding all POST or PUT parameters prior to sending to our server. the FCM token had a semicolon in it, which got encoded to a "%3A", seemingly causing the problem.
do NOT encode the FCM token.
I'm using GCM on Android.
I use InstanceID.getInstance(...).getToken(...) to receive a push token, but in some cases (after application updates or re-install) I receive an invalid token.
When the server returns a NotRegistered error, I've connected with a debugger and called InstanceID.getInstance(...).getToken(...). But this token is not valid (I've tried to send push via curl -s "https://android.googleapis.com/gcm/send" ... using this token), I receive NotRegistered error.
Why instanceID could return invalid token?
It shouldn't give invalid token.
Have you applied all procedures?
InstanceIDListenerService: When the token changes via the app
updates, etc.
RegistrationIntentService: When the token changes, you receive it via InstanceIDListenerService and call this intent to get a new
token.
Finally, I found a solution.
I worked with instanceID from two different threads. I called getToken(...) two times simultaneously. If instance doesn't have a cache, it get token from network. I think, it sends two requests in my case and there is no guarantee of it's order. So instanceID cached one token, but google cloud another one.
I'm using Google Cloud Messaging api to implement an Android client. To get a token, I do:
InstanceID ex = InstanceID.getInstance(this.getApplicationContext());
String regId = ex.getToken(senderId, "GCM", null);
And regId always contains a token, despite of I put on senderId. If I set senderId with "123", InstanceID returns a token! (But the, I don't receive notifications with this token). Why I always get a token? I expect an exception, or a null value maybe...
You may always get a token but you will not be able to use it to establish the full gcm lifecycle since instanceId is tied to your app server's senderId.
From the google documentation
Use the getToken method to prove the ownership of the InstanceID and
to allow servers to access data or services associated with the app.
The method follows the patterns of OAuth2, and requires an
authorizedEntity and scope. The authorizedEntity can be a project ID
or another InstanceID, and it determines the services that are
authorized to use the generated token. The scope determines the
specific service or data to which the token allows access.
To understand more of the lifecycle, refer to the documentation
I have tried to register my device by calling the push notification service which stores tokens inside push_notification_token table.
Registering the token is no problem but in the same app i wanted to delete the token from the table in some situation so i was trying to see if same service is helpful or not.
I tried calling the service by using URL http://mysite/endpoint/push_notifications to register the token where i will pass parameters as token is token generated from GCM service and type is android. This is working fine.
So to delete the token what is the procedure.
I solved the issue by following these steps.
1) Used DELETE method instead of normal POST method
2) Sent the tokens in the URL => http://example.com/endpoint_name/push_notifications/{token}
Like http://example.com/endpoint_name/push_notifications/abcgr123 whole token value in the end.
This will delete that token from the database.