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.
Related
I am currently using FCM notification payload to send notification to my mobile application. When the application is in foreground the badge number will increment as desired. However, when the application is in foreground the badge number will not increment.
To counteract this, I have attempted to manually increment the badge value when a notification is received in the foreground
this.fcm.onNotification().subscribe(async notificationData => {
console.log("NOTIFICATION RECEIVED 222");
console.log("DATA = "+ JSON.stringify(notificationData));
if (notificationData.wasTapped) {
} else {
console.log('Received in foreground');
console.log("BADGE VALUE = "+JSON.stringify(await this.badge.get()));
await this.badge.increase(1);
localNotifications.schedule({
id: notificationData['ticketID'],
title: notificationData['title'],
text: notificationData['body'],
//Foreground setting not affecting anything
foreground: true,
//Priority not affecting anything
priority: 2,
sound:"default",
//If lockscreen set to false, notification cant be displayed on lockscreen
lockscreen :false,
// For some reason i can only use images from the res folder although it's suppose to allow me to use images in src/asset folder as well
//48 x 48 size icon (platform/android/src/res/drawable)
smallIcon:'res://ic_launcher.png',
icon:'res://audit.png',
// badge:1
});
}
});
However, upon doing so the badge will no longer be updated when a notification is received in the background and will only be updated when a notification is received in the foreground.
After further testing, by commenting out
await this.badge.increase(1);
I realized that the value returned in the badge count does not take into consideration the badge value generated from notifications received when the application is in the background.
Is there any solution for this ?
When app is background(inactivated or closed),
if firebase notification is arrived, app badge is showed.
But when app is foreground(activated),
if firebase notification is arrived, app badge is not showed.
It seems like below.
If app is foreground, android does not display badge.
Once badge is showed, You can set badge count. It is not concerned with app status(foreground or background).
Once badge is showed, You can set badge count without notification. Anywhere and any events.
I tried like below.
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
// Used flutter_app_badger. It works only when app badge is already showed.
FlutterAppBadger.updateBadgeCount(1);
// Tried use native code invocation. It works only when app badge is already showed.
const platform = const MethodChannel('channel_name');
final dynamic result = await platform.invokeMethod('setBadge', {
'count': 1
});
});
This is invoked kotlin code from flutter.
var count = call.argument<Int>("count") as Int
val intent = Intent("android.intent.action.BADGE_COUNT_UPDATE")
.putExtra("badge_count", count)
.putExtra("badge_count_package_name", context.packageName)
.putExtra("badge_count_class_name", getLauncherMainClassName())
context.sendBroadcast(intent)
I solved this problem.
flutter_local_notifications can solve this problom.
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;
});
I have not really done much with background mode before and I have not used push notifications before.
What am trying to achieve is to give the user a warning they are going to be auto logged out 5 minutes before it happens and give them a chance to refresh their token.
It works fine when the app is active in the foreground. I pop up an alert and get them to click “ok” otherwise after 5 mins it logs out.
I have added
#ionic-native/background-mode
to my project and enabled background mode but I am not sure how to get the app to alert the user.
Is there a way to do this? Or can I only run "non UI" tasks from the background
Could I use a push notification locally from the app to notify the user rather than an alert or do push notifications only work from a server?
I used local notifications:
https://capacitor.ionicframework.com/docs/apis/local-notifications
import { Plugins } from '#capacitor/core';
const { LocalNotifications } = Plugins;
LocalNotifications.schedule({
notifications: [
{
title: 'Title',
body: 'Body',
id: 1,
schedule: { at: new Date(Date.now() + 5000) },
sound: null,
attachments: null,
actionTypeId: '',
extra: null
}
]
});
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