How to integrate Push Notification to an already existing android app?
My android app is already available on playstore and now I wants to integrate Push Notification in next release. I have implemented it using FCM and AWS SNS.
Problem is : onNewToken method of FirebaseMessagingService will get called only when we installed the app freshly. But when we update it onNewToken method never gets call. So we cannot register the token on AWS portal while updating the app. Experts please advise how to implement this in existing app?
// Use this in your splashscreen or dashboard view.
FirebaseInstanceId.getInstance().instanceId.addOnCompleteListener { task ->
if (!task.isSuccessful)
return#addOnCompleteListener
if(prefs.pushNotificationToken == "") {
//log the token
prefs.pushNotificationToken = task.result?.token?.trim() ?: ""
//send user push notification token to the server(use Patch instead of Post)
}
}
Doing this, both old and new user will have "pushNotificationToken" in prefs to be empty. Thus, we can fetch the token any time from firebase and send it to the backend.Or, also first we can check for token in our prefs and then only ask to firebase for token.
Problem is : onNewToken method of FirebaseMessagingService will get
called only when we installed the app freshly. But when we update it
onNewToken method never gets call. So we cannot register the token on
AWS portal while updating the app. Experts please advise how to
implement this in existing app?
You can call
FirebaseInstanceId.getInstance().getToken(senderId,"FCM");
At anytime to get an instance id to push to your server, this is a blocking call so make sure to do it on a background thread
Related
I would like to add push notifications to my react native App but I would need some clarifications as there are plenty of different informations and implementations all over the web on that subject.
Currently my App is communicating with a node.js backend. So I have used the Firebase Web SDK in order to send push notifications to app clients.
Now it's time to register the app clients to Firebase Cloud Messaging in order to get tokens and save them with user related data. Then to be able to send targeted notifications to specific users (node.js backend role).
I've read to use the react native firebase library and more especially the messaging module to accomplish that.
Following that Device registration token tutorial, it's pretty clear. But where is the best place to request a token ? I assume that it should be when the user logs in to the App but we are not sure to get the token on time...
With that code we retrieve an existing token:
firebase.messaging().getToken()
.then(fcmToken => {
if (fcmToken) {
// user has a device token
} else {
// user doesn't have a device token yet
}
});
Tell me if I'm right:
I understand that if the app instance has already a token, I'll get it and it's time to associated it with user related data in database. But if it doesn't, I need to listen for a new token using that :
componentDidMount() {
this.onTokenRefreshListener =
firebase.messaging().onTokenRefresh(fcmToken => {
// Process your token as required
});
}
componentWillUnmount() {
this.onTokenRefreshListener();
}
But where should I start listening for it ? On the login component ? If the user log in before getting the token and navigate to another component, so the login component will be unmounted. It will be still listening ? And then I need to update the user data with the token ?
Or simply when the user log in, I need to wait till getting the token before navigate to another component ?
I am working on IBM Mobilefirst native android app. I have written code to enable push notification. I am getting notification but I have an issue here.
On Launch of the app I am calling following code.
final WLClient client = WLClient.getInstance();
push = client.getPush();
ResponseListener listener = new ResponseListener(ResponseListener.AUTHENTICITY_CONNECT);
client.getPush().setOnReadyToSubscribeListener(listener);
challengeHandler = new AndroidChallengeHandler(realm);
client.registerChallengeHandler(challengeHandler);
WLRequestOptions options=new WLRequestOptions();
options.setAppUserId("sample");
client.connect(listener,options);
When I launch the app for the first time all the above code gets executed and the listener calls the below method
#Override
public void onReadyToSubscribe() {
WLClient.getInstance().getPush().registerEventSourceCallback(pushAliasName, "PushAdapter","PushEventSource", this);
}
After this listener is getting executed i am calling subscribe method. I get success for the subscription to push.
On the server side I call the procedure to send the push notification and it reaches the phone.
Now when my app goes to background and I get a notification . I click on the notification and app restarts and never call onRecieve method of the registered interface.
On click of the notification it relaunches the app and call the onReadyToSubscribe() again and it never calls the onRecieve method. what should I do to get the onReceive() method to be called and app shouldn't get relaunched(if app is already in background) on click of notification?
My server side security test is as below
<customSecurityTest name="AuthSecurityTest">
<test realm="wl_antiXSRFRealm" step="1"/>
<test realm="wl_authenticityRealm" step="1"/>
<test realm="wl_remoteDisableRealm" step="1"/>
<test realm="wl_anonymousUserRealm" isInternalUserID="true" step="1"/>
<test realm="wl_deviceAutoProvisioningRealm" step="2" isInternalDeviceID="true"/>
</customSecurityTest>
The useridentity is not binded to security test but i am putting it in the apps applicationdescriptor. So it never call for credentials required of challenge handler on connect.
Here I think this could be the issue in the sample code that is provided by MFP in 7.1 version security test has useridentity realm but in my case I am not using the custom useridentity realm but I am using the default wl_anonymousUserRealm. This is the issue because when i tried working with the sample code it works completely fine with all the scenarios. But with the wl_anonymousUserRealm I have this issue.
onReadyToSubscribe() method getting called everytime the application connects to the server ( even if already subscribed for push) is expected and by design.
onReadyToSubscribe() is a call back that fires at the client denoting the token exchange between client and server is complete. This is required because tokens issued to an application by mediator can change. This makes it imperative that the server always stays updated with the latest token. If not , push notification will fail with invalid token error.
When the client connects to the server , they compare tokens - client presents the token it has now and server presents what it had stored. Three cases happen:
1) In a new registration , server does not have a token. Here client passes on what it got from the mediator, server persists it and issues a success. Client fires the onReadyToSubscribe() callback to indicate push handshake is complete and client can now subscribe to aliases or tags.
2) Client has received a new token from the mediator. This does not match the one server already has. Client passes on the new token to server, server updates its records with the new token and lets the client know. onReadyToSubscribe() call back fires at client indicating successful handshake. Earlier subscriptions records stay.
3)If the tokens match, then onReadyToSubscribe() fires denoting that push handshake is complete (no changes required)
Thanks to Vivin for the suggestions.
Here was the issue in the sample code that is provided by MFP in 7.1 version security test has useridentity realm but in my case I am not using the custom useridentity realm but I am using the default wl_anonymousUserRealm.
The actual issue was wl_anonymousUserRealm generates a new random userid everytime. So when ever my app is relaunched my userid gets changed and I wont get push in onrecieve because it thinks a different user is logged into the app..
Now because I cant change the wl_anonymousUserRealm I am sending push using deviceid. Please check the below link(Adapter code as below).
https://www.ibm.com/support/knowledgecenter/SSHS8R_7.1.0/com.ibm.worklight.apiref.doc/html/refjavascript-server/html/WL.Server.html#sendMessage
check sample client code from below link.
https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/7.1/notifications/push-notifications-overview/push-notifications-native-android-applications/tag-based-notifications-in-native-android-applications/
I'm developing a GCM Application.
My issue is that when first install(launch) the app, it takes some time to get GCM token.
But My app just 'POST' to server to register the user.
So at first launch , because of registering when GCM token is null, my app always register GCM token null at first time.
How could I solve this problem?
Actually I tried to solve this by using Progressbar but Progressbar doesn't show like the sample project of GCM provided by google.
How do you guys solve this problem?
You should only send the token to your application server after it has been returned by your InstanceID.getToken call which should not happen on the main thread.
You should use an IntentService that will get the token AND send it to your application server, then if necessary, you can use a BroadcastReceiver/LocalBroadcastManager to let your UI know when the the token has been successfully sent to the application server.
Consider the GCM quickstart sample. In particular look at the RegistrationIntentService that gets the token and sends it to the server.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token);
This should be quite an easy fix. if you followed googles example then the registering to the GCM should be done using an async task class called RegisterApp.
The async task has 3 main methods OnPreExecute, DoInBackground and OnPostExecute. DoInBackground is the method that runs on a seperate thread and that will be why it is failing currently. It hasn't finished running that thread and you have already sent an empty regID to your backend. This wont be failing next time you login to your app because more than likely you are saving the regId to a file and reading it if your app is already registered to the GCM
You can send the regId to your backend in either the DoInBackground, which is where you should be registering to the GCM, or in the OnPostExecute.
I do it in the DoInBackground method straight after it registers as this is the only part that runs on a separate thread and if for some reason it fails to send to my backend it is handled on a seperate thread to the main UIThread.
Dont forget you will also need your current method of sending it because the RegisterApp wont run if your app is already registered.
Hope this helps.
This is the sample i followed. Here
Currently it works for me as the activity that handles the registering is locked to portrait and not much else is going on, but each to their own.
Arthur makes some valid points
I am developping an android app based on firebase that connects to the Nest API. While it worked for some time, it now rejects authentification.
I get the folowing error "The active or pending auth credentials were superseded by another call to auth" when I'm pretty sure firebaseRef.auth() method is only called once...
EDIT : I'm getting close to the 1000 Users limitation after wich we should request more users from Nest.
Any idea where this is comming from ? Can it be comming from the online service I am calling or is this necessarilly due to my code ?
thanks.
P.
We discovered that every time the user is passed through the Works with Nest web sign up dialog, it generates a new auth token. Is it possible you've run through the process on multiple devices and generated a new auth token, invalidating your previous one?
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.