Single Device Push Notifications (FCM Registration Token) not working - firebase

I'm using react-native-firebase with firebase-messaging to implement push notifications.
While I can send push notifications to everyone, I'm unable to send them to individuals. To my knowledge, all I need is the FCM Registration Token which I retrieve by following the documentation
firebase.messaging().getToken()
.then(fcmToken => {
if (fcmToken) {
console.log("fcm token", fcmToken);
} else {
console.log("fcm token", "null");
}
});
The token I receive is a plausible token, but when I copy that token from the logs into the firebase console and try to send it to a single device, nothing is received. (If I push to a user segment, it's received by all devices with the app installed).
As I can not test for iOS, this might or might not also be a problem on iOS.
In my build.gradle file, the firebase relevant libraries are included like so:
compile(project(':react-native-firebase')) {
transitive = false
}
implementation "com.google.android.gms:play-services-base:15.0.1"
implementation "com.google.firebase:firebase-core:16.0.1"
implementation 'com.google.firebase:firebase-auth:16.0.2'
implementation "com.google.firebase:firebase-messaging:17.1.0"
In the MainApplication.java file I add them to the list of ReactPackages.
new RNGoogleSigninPackage(),
new RNFirebasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebaseAuthPackage()
My AndroidManifest does not have any Firebase relevant changes as I discovered that push notifications were working even without them. (While trying to implement push notifications I noticed that all phones were receiving them except the one I was actively working on - so I rolled back the code.)
edit: I managed to receive one single device notification. Without any changes, it was suddenly working exactly once. Now it doesn't work anymore.

Related

How to run a function when a notification is received with Firebase Messaging ^8.0.0-dev.8 in Flutter?

Hello I'm using Flutter to build my app and I need to to show an alert whenever a new notification is received.
I've been using firebase_messaging 7.0.3 but I run into an error with onBackgroundMessage. A quick Google search helped me find out that the error I was getting hasn't been fixed yet. However one of the devs posted an update 20 days ago about a new version of the package which fixed that issue.
The new version removed the old onMessage handlers and introduced new ones.
Now they got new event handlers which return streams, but haven't been able to make them fire by using the
.listen() function. Whenever I receive a notification a get a this: D/FLTFireMsgReceiver(22032): broadcast received for message printed in the console but the code in the .listen() doesn't get executed.
Here is a link to an article on Firebase Flutter that is a guide for using the new version of the package.
Here is my code:
...
FirebaseMessaging.onMessage.listen((event) {
// do something
});
FirebaseMessaging.onMessageOpenedApp.listen((event) {
// do something
});
FirebaseMessaging.onBackgroundMessage((message) {
// do something
return;
}
...
A solution I found to get the events to fire was to always call:
await FirebaseMessaging.instance.getToken();
right after the
await Firebase.initializeApp();
Once I call that, the FirebaseMessaging.onMessage.listen catches the event as expected.
I was getting the same log when my app is in doze mode for the Data notification with high priority.
This is because of some issue in the firebase-messaging plugin.
Firebase_messaging plugin internally uses JobIntentService to process background fcm notifications
JobIntentService has one constraint in Android O or later versions, when running a Job it will be subject to standard JobScheduler policies. The job will not run immediately while the device is in doze mode. (reference link)
The same issue was raised in the firebase_messaging git repository(bug link)
Solution
One Signal(another push notification provider) solved this issue by having a modified version of JobIntentService. (OneSignal Solution)
At a high level, it uses wake locks for high priority fcm notifications to run service even in Android O and above.
Add this Pull Request changes in your ide by editing respective files.
TL;DR
Add this Pull Request changes in your ide by editing respective files.
Send Data notification with High priority.
FCM Payload:
{
"message": {
"token": "fcm_client_token",
"data": {
"title": "Hello",
"body": "Test Message"
},
"android": {
"priority": "high"
}
}
}

Messages successfully sent, but no notifications visible in Firebase Cloud Messaging

Messages are reported as successfully sent, but no pop-up notifications appear.
With onMessage it is sometimes possible to log the message.
Requesting an FCM token only works on localhost.
When tried on the .com site, the error message depends on whether I use the PC or chromebook - the error messages generated are different.
I have used 2 different devices, but always Chrome browser. The cloud function writes the message and the FCM response to the function log, so it confirms success in sending.
When I deleted onMessage from the recipient webpage there was no sign of any notification.
The webpage is open during these trials. This is web/javascript.
Notification permission is set to allow, in both devices.
I have spent hours on web searches trying to find any hint as to what to try.
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': '593287500713'
});
const messaging = firebase.messaging();
the relevant code which runs with the webpage
messaging.onMessage(function (payload) {
console.log('Message received. ', payload);
});
I assume that without onMessage, the notifications should appear based on the Firebase SDK, but they don't. WRONG ASSUMPTION
When in the background, nothing appears. (I think notifications are supposed to appear automatically.)
I can request and receive an FCM token when running on local host but the same code throws an error when deployed. "Request is missing required Authentication..."
I have been in contact with support # Google who have assured me that this suggestion, and then another would 100% fix the problem. Nothing made any difference.
I have tried the code snippets in the Firebase docs and also github examples.
If I could find existing code that works, that would be a great start, because I think that finding a solution after about 40 hours of effort is hopeless.
Have I missed something obvious?
UPDATES....
I have found two reasons for not seeing notifications.
1) My PC had a setting which seems to have partially suppressed the display. Unexpected because YouTube notifications do display. (Open notification tray on far right bottom of screen. "focus assist" with a crescent moon symbol. If when clicked it says "on" or "alarms only" I think this restricts what is seen.)
2) My assumption based on the Firebase docs and video was that onMessage() is to prevent notifications when the user is on the webpage and to allow the developer to ignore or handle the notifications within the page. Half right. Apparently the notifications are default ignored UNLESS onMessage() does something with them. The docs give snippets of code for onMessage() but only how to log to the console.
Also, found an amusing problem. Now that my PC has registered the recipient of the messages, it receives them even if that recipient is signed out and has signed in on another device. That sounds like a problem.
The currently working version of the code. This goes in the webpage / app (NOT in the messaging-sw.js file
The introductory video to messaging suggests that it is bad UX to have notifications from a website popping up when someone is on the website. Therefore the code can include onMessage() to either ignore the notification or to handle it within the page.
The docs give a version of onMessage that just logs the notification to the console and has just a comment about doing something else.
Other parts of the docs explain that the system automatically displays notifications.
Therefore I inferred that without onMessage() the notifications would appear automatically.
It seems I was wrong.
It has taken me a massive amount of time to figure this out and to find some code to make the notifications appear. (Even now I am not sure I have grasped what is happening, but the following seems to work)
This goes in the web page / app. (Not in the messaging-sw.js. Putting it there will throw an error "using window methods")
[Do note that I also found my PC was set in a way that seemed to allow YouTube to send notifications, but was preventing the display of FCM notifications. (See explanation in question)
So far I have tested this when the use has the webpage open, the webpage in the background and when the browser is closed. Notifications appear with the default sound and are listed in the notification tray.
This also happens if the recipient is signed out of the webpage and signed in on another device.. the messages continue to go to the same device.
Messages go to devices not to users]
messaging.onMessage(function (payload) {
try{ //try???
console.log('Message received. ', payload);
noteTitle = payload.notification.title;
noteOptions = {
body: payload.notification.body,
icon: "typewriter.jpg", //this is my image in my public folder
};
console.log("title ",noteTitle, " ", payload.notification.body);
//var notification = //examples include this, seems not needed
new Notification(noteTitle, noteOptions);//This can be used to generate a local notification, without an incoming message. noteOptions has to be an object
}
catch(err){
console.log('Caught error: ',err);
}
});
``````````

Firebase messaging failing on flutter after some time

I'm having an issue with FCM on flutter. I have implemented messaging from my server so I'm storing my phone token for each user.
The thing is that when a user logs in for the very first time everything works properly, messages are being sent and user gets notified.
If I do not use the app during the weekend, on Monday I try to send a message by doing some actions on my app but messages are not being sent. I can see my token stored properly in my database.
I'm using firebase_messaging 2.1.0 for flutter.
This is how I get my token
_fireBaseMessaging.getToken().then((token){
_myPhoneToken = token;
});
1-I know token may change when:
App deletes Instance ID
App is restored on a new device
User uninstalls/reinstall the app
User clears app data
But none of this happens.
Any advice on how to handle this scenario? thanks in advance.
UPDATE
Provided you have setup the FCM sdk the right way (but you said that it works the fist time you install the app, so I guess so).
Provided that you are sure that the device_token you are using is the one of the device on which you are expecting to receive the notification (check if it's still the same), you should get on this device your notification quite soon if you use "priority" : "high".
{
"to" : "device_token",
"priority" : "high",
"notification" : {
"sound": "default",
"body" : "Test Notification body",
"title": "Test Notification title"
}
}
This method call
_firebaseMessaging.getToken().then((String token)
return always the new token even if it has been updated. So if you print this out on your device and you send a notification on this token without error, there's no reason why you should not get the token if the device has a valid internet connection active.
It's true that the device token can change during time. If you uninstall and reinstall the app, you can see the token will change and if you try to send a notification on the old one, you will get an error.
If instead the token will change during application lifetime, you can be notify on your server side by listening:
_firebaseMessaging.onTokenRefresh.listen((newToken) {
_fcm_token = newToken;
// send the new fcm to your server
});
So first of all I suggest you to be able to send a notification to a device with Postman. Check if the token you are using is still the one on the device. Then you can try to uninstall and reinstall the application and try to use the old token. You will get an error. Then try to send to the new one, and you should get your notification.
Then wait for some days and try again, check if the token has changed or not and if it's not changed you should be able to send the notification without problems with the same token.
Also be aware that data message on Android if the app is terminated are still not supported.
Some networks/router/mobile can cut the connection between firebase library and firebase server due to inactivity (5min without message). This cut may be detected by the library up to 30min (FCM heatbeat interval).
These are some links discussing this issue:
https://github.com/firebase/quickstart-android/issues/307
Android: Delay in Receiving message in FCM(onMessageReceived)
I contacted firebase support but they told that since the issue is caused by external part they cannot fix it (I suggest decreasing heartbeat interval ...)
I fixed it in android using an interval job which apply these instructions:
context.sendBroadcast(new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"));
context.sendBroadcast(new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));
You may write this specific code for Android side and should find something similar for ios side.

iOS FCM data only message does not call messaging:didReceiveMessage

Firebase Messaging version 5.6.0. I am attempting to handle a data only message in the foreground via Firebase Messaging on iOS 9.0 (10 if needed), but it is not calling FIRMessagingDelegate's messaging:didReceiveMessage per the documentation. I see the message come in # FIRMessaging.m's appDidReceiveMessage:message, but never comes through to the delegate.
This is the snippet from the cloud function that sends data to the topic per sending to a topic:
const message = {
data: {
test: '123'
}
topic: 'example'
}
admin.messaging().send(message);
Did I miss something?
Update: I do receive the data if I implement application:didReceiveRemoteNotification:userInfo
fetchCompletionHandler:completionHandler.
Thanks to Kat at Firebase support, here is the answer.
Use legacy sendToTopic instead of send, as send quietly adds content_available=1 which gets treated as APNs silent notification. Here is the updated version:
admin.messaging().sendToTopic('example', {
data: {
test: '123'
}
});
// Always use strings for key/values in the data object.
Below verbatim from Kat at Firebase support:
How the FCM data message is handled would depend on your setting for content_available.
If you have content_available = 1, the message is sent via APNs and is treated similar as an APNs silent notification. This is handled in the application:didReceiveRemoteNotification: callback when the app is running in foreground or background (i.e. not killed). See this related StackOverflow post for more information.
Without content_available, the message is sent via FCM direct channel. This only handled in the messaging:didReceiveMessage: when app is in foreground.
Note that messages sent via the Admin SDK's send() method uses the FCM HTTP v1 API which have content_available=1 by default, so they are always sent via APNs. If you want to configure the content_available field, you'll need to use the Admin SDK's sendToDevice() method which uses the legacy protocols.
In addition, here is the list of legacy protocols.

Push Notifications on iPhone without alerts to the user

I have searched the web on my question but did not find anyone answering it. This looks weird as I am sure other people face similar issue.
At the moment my app is receiving push notification fine. I have a chat module where user can speak and whenever a new message is being sent, the other phone receive a push notification to update the chat.
You could say no issue there, but the problem is when the user is out of the application: he is still receiving those notifications showing a banner on the screen, and I want to dis-activate this. Basically I want push notification without alerts to the user. Is there a way to do that?
Thanks
Just leave the sound property of your push notification payload empty, omit the alert/text property and add "content-available":1 and your notification will be silent. This is often referred to as silent push notification or "push-to-sync".
See documentation here:
For a push notification to trigger a download operation, the
notification’s payload must include the content-available key with its
value set to 1. When that key is present, the system wakes the app in
the background (or launches it into the background) and calls the app
delegate’s
application:didReceiveRemoteNotification:fetchCompletionHandler:
method. Your implementation of that method should download the
relevant content and integrate it into your app
So your payload should least look like this:
{
"aps" : {
"content-available" : 1,
"sound" : ""
},
"chat-message" : "Hello World!"
}

Resources