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;
});
Related
I'm currently using this library in react-native to schedule local notification, when i tap of notification either from notification centre or from top of the app, i want to redirect the user to specific screen. Currently react-native-push-notification lib using old UILocalNotification classes which are already deprecated.
Below is my code to configure local notification.
onNotification is a callback method triggers when user launches the app from notification centre for iOS and similarly onAction is for Android.
/**
* To configure for local notifications
*/
export function localNotificationConfigure() {
PushNotification.configure({
onNotification: async function (notification) {
console.log('notification.data', notification.userInteraction);
notification.finish(PushNotificationIOS.FetchResult.NoData);
},
onAction: async function (notification) {
console.log('notification', notification.userInteraction);
},
permissions: {
alert: true,
badge: true,
sound: true,
},
popInitialNotification: true,
requestPermissions: Platform.OS === 'ios',
});
}
Is there any way that i can achieve this. Is it because of lib using UILocalNotification which is deprecated and i'm not able to get the action back in the code. Any help is appreciated.
This link helped me in achieving my desired functionality.
I'm setting up notifications for a react-native app by using react-native-firebase. iOS works, in Android I have strange behaviour, that the notification banner only shows if there is already another notification sitting in the bar.
Problem Demonstration:
send the same message twice, the first message is only displayed in the upper bar, the second message is shown with a banner.
Goal:
I want the notifications to be always shown with a banner.
I listen for messages on android and generate local notifications. I was hoping to have the notification always showing by setting show_in_foreground: true. But that is only partially the case. The behavior in the gif above is the same for the app being in the foreground or background.
this.messagingListener = firebase.messaging().onMessage((message) => {
const { data} = message;
const localNotification = new firebase.notifications.Notification({
show_in_foreground: true,
sound: 'default'
})
.android.setChannelId('fcm_default_channel')
.setTitle(data.title)
.setBody(data.body)
.android.setColor('#222222') // you can set a color here
.android.setPriority(firebase.notifications.Android.Priority.High);
firebase.notifications()
.displayNotification(localNotification)
.catch(err => console.error(err));
});
This issue seems to be a Android 10 problem. The notification works fine on Android 9.0. I will update this answer as soon as i know more about a fix for Android 10.
I have function in Firebase Cloud Functions which is used to send notifications to specific users within my app and has as the notificationContent the following code:
const notificationContent = {
notification: {
title: "My Notification Title",
body: "My Notification Body",
icon: "default",
sound : "default"
}
};
I have tried to use collapse_key: "unique_key" but it has no effect. I read the has an effect only when the device is offline. I also have used a tag: "unique" but every time a new notification arrives, it will override the oldest one.
I there any way in which I can achieve this with Firebase? If I receive more then one notification, to be grouped in a single one?
Thanks in advance!
If you want to use more customizable and advanced notification features.
You should only send FCM with data payload, and create notification at android client side.
Remember that if you send FCM with notification payload or notification + data payload, the notification will be created by android core system and BroadcastReceiver's onReceive method won't being called if your app is on background.
If you send FCM with data payload, it will call onReceive all the time, so you can produce custom notification manually at android client side. (most app uses latter method.)
I hope this link would be helpful.
I had this same confusion and realized I misunderstood what collapseKey and tag are for.
collapseKey will limit the number of notifications a client receives while they're offline, tag is what will stack notifications together in the drawer.
So for a typical cloud function, it should look like this:
const notification = {
notification: {
'title': 'Interesting title',
'body': 'Hello, world'
},
'data': {
'whatever': whatever,
},
'android':{
'collapseKey': collapseKey,
'priority': 'high',
'notification': {
'tag': tag,
}
},
'token': fcmToken
};
admin.messaging().send(notification)
Note that the "tag" parameter sits inside of the android notification, not the top-level notification.
The easiest and most flexible solution is to extend the FirebaseMessagingService and handle the notification yourself. But first instead of using notification on your notificationContent in your cloud function, you have to change that to data so that you send a data message instead of a notification message. The difference is that the notification message will have an implicit collapse key (the package name of the app), while the data message won't have one. But the data message needs to be handled on the client or else it won't be displayed.
Here's a sample of what you'll need for your FirebaseMessagingService:
public class MyFCMService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification() != null) {
//this notification was sent from the Firebase console, because in our cloud function, we are using the DATA tag, not the notification tag
//so here we have to handle the notification that was sent from the console
...
} else if (remoteMessage.getData().get(KEY) != null) {
//this data message was sent from our cloud function
//KEY is one of the keys that you are using on the cloud function
//in your example, you are using the keys: title, body, icon, sound
//display the notification to the user
...
notificationManager.notify(TAG, ID, notificationBuilder.build());
//you have to use the same TAG and the same ID on each notification if you want your 2nd notification to simply update the text of the first one, instead of showing as a new notification
}
}
}
PS. When you send a notification from your cloud function (well if you use the data tag, it's actually a data message, not a notification message), then this method will be called, regardless if the app is in the background or in the foreground. HOWEVER, when you send a notification from the firebase console, this method will be called ONLY if the app is in the foreground. If the app is in the background, the Firebase SDK will handle the notification and show it to the user. In some cases, it makes sense to show a notification only when the user is not running the app, for example if you want to advertise some new features of the app. In that case, what you can do is use a unique tag on the notification console (e.g. "display_in_foreground") and check that tag on the client. If you have set that to true, you can show the notification even to users that are currently running the app, or if it's false you can choose not to show the notification. This check will happen only if the app is in the foreground. If it's in the background, this won't be called at all and the SDK will handle to show the notification.
I'm implementing push notifications in a Ionic 2 app for Android. For this, I'm using the following function:
registerPush() {
this.push.register().then((t: PushToken) => {
return this.push.saveToken(t, {ignore_user: false});
}).then((t: PushToken) => {
this.push.rx.notification().subscribe(msg => {
// execute some code
});
});
}
With this, I'm able to receive push notifications sent from server. While the app is in foreground, the execute some code part is run without problems. While the app is in the background (I'm using the background plugin), the push notification is received, but when I click on it nothing happens.
I want to execute the notification code in this situation too, and open the app when I click it. Is there any way to achieve this?
UPDATE
I've read the plugin documentation and changed the code accordingly:
registerPush() {
this.pushNotifications = Push.init({ android: { senderID: "xxxxxxxx" } });
this.pushNotifications.on('registration', data => {
// send token to server
});
this.pushNotifications.on('notification', data => {
// handle notification
});
}
With this, and with content-available set to 1 in the notification sent from server, the app executes the code whether I'm inside it or not.
However, I'm still not able to put it in foreground when I click the notification.
I am successfully able to send push notifications using IONIC Framework. But these notifications doesn't looks like I receive other android notifications, rather it these looks like normal Javascript alert.
Is there any setting to set push notification type like (alert or something else) ?
I go through the following link : https://devdactic.com/ionic-push-notifications-guide/
If someone has faced and resolved this, then please comment.
First screenshot shows push notification as Javascript alert.
Second screenshot shows default Android notification after locking phone's screen.
Third screenshot shows default Android notification after unlocking screen
I solved this problem by applying below code to $ionicPlatform.ready in my app.js file which shows notifications with onNotification event, if onNotification is not present then IONIC show default Javascript alert.
var push = new Ionic.Push({
onNotification: function(notification) {
var payload = notification.payload;
console.log(notification, payload);
},
pluginConfig: {
ios: {
alert: true,
badge: true,
sound: true
},
android: {
sound: true,
vibrate: true,
forceShow: true,
iconColor: "#601dc2"
},
}
});
While working with push notification you have Two possibilities to get notification One in the notification tray on the head of screen while your app is in background mode and Second when you are working with your app in foreground mode
First one is display like other notifications to notify that you got a notification for your app with message and logo whatever you set
But for other notification it is just use to get the data and message whatever you passed through it, and now its on you that how you want to show it in the application
Either you can set a div and hide show it when notification display with the design and position as you like or as per your app theme
<script>
function devicePushNotification(data)
{
if (data.additionalData.foreground == true)
{
$("#setNotificationText").text(data.message);
$("#setNotificationText").css("display","block");
}
}
</script>
<div style="width:50%;margin: 0 auto;display:none" id="setNotificationText">
</div>
Or you can just alert the message that you got a notification for anything you have passed like,
<script>
function devicePushNotification(data)
{
if (data.additionalData.foreground == true)
{
alert(data.message);
}
}
</script>
So, if you get the notification successfully, then you just have to create any well formed container to display it.
Hope this helps you