Firebase Notification Not Receive in onMessageReceived when app is in background - android

I an using FCM for sending a notification in my app and all work perfectly but when my app is in background then the notification is handle by android system notification tray
i want to handle my notification from myself i am sending this payload for send the notification
$fields = array(
'notification' => $notification,
'to' => '/topics/updates'
);
this will call my onMessageReceived when my app is in forground but when my app is in background this will not call my onMessageReceived the request is handled by system itself
i want to call my onMessageReceived when my app is in background
i am also try to remove notification key and only send data key like this
$fields = array(
'data' => $notification,
'to' => '/topics/updates'
);
but when i send the request from above field onMessageReceived is not called in both the condition in forground and background
i am try this in my xiaomi redmi note 4 (oreo) , redmi 4x(android 10) and android emulator(marshmello)
i am follow this ans for solve my problem but not work for me How to handle notification when app in background in Firebase
my FCM version is 17.3.4
and my android studio version is 3.5.3

If the data message is not received then the payload might be wrong. Here is my payload example (.js, but the structure should be pretty much the same):
const payload = {
data: {
title: finalTitle,
body: message,
icon: icon
},
topic: channel
};
admin.messaging().send(payload)
.then((response) => {
return
})

sorry for post this stupid questions FCM work in background when we post only data key not notification key
my mistake is this i wrap my notification builder by this
if (remoteMessage.getNotification() != null) {
// other code
}

Related

Expo: don't show notification if app is open in foreground

I am developing a react-native messaging app with Expo. Every time a user receives a new message, I send a notification from my server.
Is there any way to not display the notification if the app is currently open?
Right now I am using this as soon as the notification is received:
Notifications.dismissNotificationAsync(notification.notificationId);
But there is a 0.5 second delay where the notification has time to appear in the tray and trigger a sound before it gets dismissed. I would like to not show it at all.
When a notification is received while the app is running, using setNotificationHandler you can set a callback that will decide whether the notification should be shown to the user or not.
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
When a notification is received, handleNotification is called with the incoming notification as an argument. The function should respond with a behavior object within 3 seconds, otherwise the notification will be discarded. If the notification is handled successfully, handleSuccess is called with the identifier of the notification, otherwise (or on timeout) handleError will be called.
The default behavior when the handler is not set or does not respond in time is not to show the notification.
If you don't use setNotificaitonHandler, the new notifications will not be displayed while the app is in foreground.
So you can simply set setNotificationHandler to null when your app is initialized.
Notifications.setNotificationHandler(null);
See Documentaition
The answer is yes to your question
Is there any way to not display the notification if the app is
currently open?
The default behavior of Notification in Expo is not to show notification if the App is in foreground. You must have implemented Notifications.setNotificationHandler similar to the following code -
// *** DON'T USE THE FOLLOWING CODE IF YOU DON'T WANT NOTIFICATION TO BE DISPLAYED
// WHILE THE APP IS IN FOREGROUND! ***
// --------------------------------------------------
// Sets the handler function responsible for deciding
// what to do with a notification that is received when the app is in foreground
/*
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false,
}),
});
*/
If you don't use setNotificaitonHandler, the new notifications will not be displayed while the app is in foreground.
Use below code snippet. It works on press notification.
_handleNotification = async (notification) => {
const {origin} = notification;
if (origin === ‘selected’) {
this.setState({notification: notification});
}
//OR
if (AppState.currentState !== 'active') {
this.setState({notification: notification});
}
}
I assume you setup a simple FCM - Firebase cloud messaging
And use that to push messages to the client?
The official Expo guide has a section for receiving-push-notifications
This is the actual workflow of FCM (weird can be called as a common issue) that it'll handle the notifications by itself when the application is in the foreground.
The solution which i did for my project was to create a custom notification JSON rather than using their default template which won't be parsed by FCM.
{
"hello":" custom key and value",
"message":{
"SampleKey":"Sample data",
"data":{
"SampleKey" : "Sampledata",
"SampleKey2" : "great match!"},
}}
In console you can add your own custom JSON objects, and when you get the notification parse the notification by using these objects, then you will be able to override that issue.
You can also add a channel for the request to categorize your notifications
this.createNotificationListeners = firebase.notifications()
.onNotification((notification) => {
let{ hello,data,message} = notification;
});

FCM Data Message should be non-collapsibl by default

Based on the documentation, it is my understanding that there are two types of messages that Firebase can send: Notification and Data. Also, they can be either collapsible or non-collapsible with non-collapsible being the default for data messages. This would mean that each message is delivered to the client app. See below:
However, when I send data messages to my client they are collapsed. For example, I send one and it appears in the notification bar with no problem but if I don't open it and another message comes in, it is replaced by the new message. Here's some of my code.
Data message:
//create the notification payload
let payload = {
data: {
title: 'Title',
context: context,
parent: parent,
body: user + " commented on your contribution.",
sound: 'default'
}
};
//send the notification
return admin.messaging().sendToDevice(userToken, payload).then(ok =>{
console.log('Notification sent to: ' + submitter);
}).catch(error => {
console.log('Could not send notification.');
});
What am I doing wrong? I want each notification to appear and not be replaced.
You are debugging at the wrong end. The actual problem is on the client side where you are posting the notification.
While posting the notification if the notification id is the same Android OS will replace the existing notification.
Look for the notify() in your code. Refer to this doc for more details : https://developer.android.com/reference/android/app/NotificationManager.html#notify(int, android.app.Notification)

Background Firebase Push Notifications in Cordova

I am using a phonegap-plugin-push for receiving notifications in Cordova Application. I am deploying on android Marsh-mellow for testing.
I want to see and store the contents of the Notifications received through Firebase Console when the app is in background.
Here is my Code -
document.addEventListener("deviceready",onDeviceReady,false);
function onDeviceReady(){
var push = PushNotification.init({ "android": {"senderID": "91254247XXXX"}});
push.on('registration', function(data) {
console.log(data.registrationId);
//document.getElementById("gcm_id").innerHTML = data.registrationId;
});
push.on('notification', function(data) {
alert("On Notification function!!");
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
console.log("notification event");
console.log(JSON.stringify(data));
alert(JSON.stringify(data));
//Do something
});
push.on('error', function(e) {
alert(e);
});
}
When the app is in foreground (on screen) I receive the contents (title, message, data, etc.) properly and I am able to see them in alert box directly in the app.
But when app is in background (not on screen but running in backround), I get the notification in Notification Area. When I click on the notification received, it is redirecting me to the last opened page in the app.
The function push.on('notification', function(data) {} is not called. No alert messages are shown. Can someone help me how to access the notification message and data?
I found the answer after 2 days of research. We have to set "content-available" to 1 in the data field. Else it wont call on notification block if app is in background.
And this is not possible as of now through Google Firebase Console.
We have to send our custom payload messages (data or notification or both) seperately using any one of the firebase servers.
Detailed info can be found on the plugin's GitHub Page on background notifications.
I used NodeJs firebase-admin. I followed these setup guidelines and these steps for sending messages and it worked for me.
Here is my working code (NodeJS) -
var admin = require("firebase-admin");
var serviceAccount = require("pushnotificationapp-xxxxx.json"); //this is the service account details generated from server
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://pushnotificationappxxxxx.firebaseio.com/" //your database URL here.
});
var registrationToken = "eYjYT0_r8Hg:APA91bG0BqWbT7XXXXX....."; //registration token of the device
var payload ={
"data": {
"title": 'Test Push',
"message": 'Push number 1',
"info": 'super secret info',
"content-available": '1' //FOR CALLING ON NOTIFACATION FUNCTION EVEN IF THE APP IS IN BACKGROUND
}
};
//send the notification or message
admin.messaging().sendToDevice(registrationToken, payload)
.then(function(response) {
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
UPDATE :
I implemented the same using php server too.
Here is my working php code for sending notifications using HTTP POST to FCM server-
<?php
$url = 'https://fcm.googleapis.com/fcm/send';
$data =
array(
"to" => "eYjYT0_r8Hg:APA91bG0BqWbT7XXXXX.....",
"data" => array(
"title"=> 'Test Push',
"message"=> 'Push number 1',
"info"=> 'super secret info',
"content-available"=> '1')
);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => array("Content-Type:application/json",
"Authorization:key=AAAA1HfFM64:APA91XXXX...."), //this is the server authorization key from project settings tab in your Firebase Project
'method' => 'POST',
'content' => json_encode($data)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { echo "Caught an error"; }
else{
echo $result;
}
?>
i was going through the same issue but i added "content-available": '1' also but my phone was not receiving any background push.
Finally i found that it was issue with my phone as mentioned here: https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#huawei-and-xiaomi-phones
Huawei and Xiaomi Phones
These phones have a particular quirk that when the app is force closed that you will no longer be able to receive notifications until the app is restarted. In order for you to receive background notifications:
On your Huawei device go to Settings > Protected apps > check "My App" where.
On your Xiaomi make sure your phone has the "Auto-start" property enabled for your app.
On your Asus make sure your phone has the "Auto-start" property enabled for your app.
Hope it will help someone.

Firebase push notifications vibrate in background

I'm using com.google.firebase:firebase-messaging:10.0.1 for Android and trying to make the device vibrate while application is in background and a push notification is received.
I send following json to FCM server:
to: 'topics/...',
notification: {
title: 'New Message',
body: 'top security body',
sound: 'mysound',
action_click: 'top_security'
}
When the app is in foreground, the onMessageReceived method of FirebaseMessagingService is triggered and I can add vibration. But, when the app is in background, onMessageReceived is not called and I have no control on the vibration. My first thought was to use data block instead both for background and foreground, but iOS client does not receive pushes in background if there is no notification block.
So how can I add vibration to push notification when the app is in background?
P.S. When I turn on vibrate mode on the device, the push notification cause vibrating instead of playing the sound.
Use data payload instead of notification payload because data payload will trigger onMessageReceived even though the app is background or foreground. Your request will look like this
data: {
title: 'New Message',
body: 'top security body',
sound: 'mysound',
action_click: 'top_security'
}
To retrieve the data from data payload inside onMessageReceived, call remoteMessage.getData(); which will return the result in a Map<String,String>
For example:
Map<String, String> data = remoteMessage.getData();
String title = data.get("title");
String body = data.get("body");
Then customize the notification as you want with that data.
Hope this helps :)

FCM console push works but server push does not

GCM was working fine but now fcm do not recive any notification if it was sent by server it only work if o send from firebase console I am almost sure the problem is in array form i have in app:
String messageBody = remoteMessage.getNotification().getBody();
and in php:
$fields = array(
'registration_ids' => $this->devices,
'data' => array( "message" => $message ),
);
what do you think please
In your question you are sending a data-message, which is a message with a payload like:
{"registration_ids" : ["token1"], "data" : { "key1" : "value1"}}
To receive the data payload (in the example: key1:value1), the client app should to use:
String value1 = remoteMessage.getData().get("key1");
FCM also supports display-messages.
Example:
{"registration_ids" : ["token1"], "notification" : { "body" : "hello"}}
These messages are automatically displayed when the app is in background.
And they call onMessageReceived() only if the app is already open and in foreground.
In this second case you can access the field of the original notification via: remoteMessage.getNotification().getBody()
Display messages can also include a {"data" : { "key1" : "value1"}}.
If the app is in foreground it can access these values like a data-message.
If the app in bakground you need to wait until the user click the notification and starts an activity.
At that point you can access the data via: getIntent().getExtras()
PS: the notifications sent via Firebase Web Console are only display-messages.

Categories

Resources