I am using react native firebase library for push notification and i am playing two different sound for two different notification so i am playing some .mp3 sound for one notification and default for other one so problem is app is playing only that sound which is coming in first notification for app and for rest notification playing the first played sound so I think the issue is notification information is not updating that's what it is playing the same sound for all the notification which app got for first notification.even we are getting right information in notification data but it is not updating the sound.
Version:
react-native-firebase:"4.3.8"
react-native:"0.56.1"
yes I am getting data from firebase and below is my code to set Sound for notification.
this.notificationListener = firebase
.notifications()
.onNotification((notification: Notification) => {
const channel = new firebase.notifications.Android.Channel(
'test-channel',
'Test Channel',
firebase.notifications.Android.Importance.Max
).setDescription('My apps test channel');
if (notification && notification.data) {
const data = notification.data;
if (data && data.messageKey) {
//here I set the sound on basis of notification data to the channel
...
}
}
// Create the channel
firebase.notifications().android.createChannel(channel);
// Process your notification as required
notification
.android.setChannelId('test-channel')
.android.setSmallIcon(Images.logoSmall);
firebase.notifications()
.displayNotification(notification);
});
1) In android, add your custom sound file to [project_root]/android/app/src/main/res/raw
2) Create notification channel
const channel = new firebase.notifications.Android.Channel('channel_name', 'channel_name', firebase.notifications.Android.Importance.High)
.setDescription('channel_name')
3) Add sound into notification .setSound('default')
firebase.notifications().android.createChannel(channel);
const localNotification = new firebase.notifications.Notification({
sound: 'default',
show_in_foreground: true,
})
.setNotificationId(new Date().valueOf().toString())
.setTitle(noti_payload.title)
.setSound('default')
.setBody(noti_payload.message)
.setData({
now: new Date().toISOString(),
payload: noti_payload,
})
.android.setAutoCancel(true)
.android.setBigText(noti_payload.message)
.android.setLargeIcon('ic_launchers')
.android.setVibrate(1000)
.android.setColor('#74c900')
.android.setColorized(true)
.android.setChannelId('channel_name') // e.g. the id you chose above
.android.setSmallIcon('ic_launchers') // create this icon in Android Studio
.android.setPriority(firebase.notifications.Android.Priority.High);
firebase
.notifications()
.displayNotification(localNotification)
Important Note:-
After doing above step please uninstall app and delete bundles, because some time cached bundle asset contain default sound and changes are not reflected.
every time you change sound you need to build bundle again
Please check following link also
https://rnfirebase.io/docs/v4.0.x/notifications/reference/Notification
setSound() was deprecated in API 26. Use NotificationChannel.setSound() instead.
Related
I am building an application similar to Swiggy, So When getting a new order from a customer, I am triggering a push notification, At that time I need to trigger a different Horn Sound.
Modules used:
// For Firebase notification
#react-native-firebase/messaging
react-native-push-notification (for local notification)
// Background lisner to trigger sound
import messaging from '#react-native-firebase/messaging';
import SoundPlayer from 'react-native-sound-player'
messaging().setBackgroundMessageHandler(async(remoteMsg) => {
try {
SoundPlayer.playSoundFile('air_horn', 'mp3')
} catch (e) {
console.log(`cannot play the sound file`, e)
}
})
Here! The problem is Sound is not triggered when notification is received.
Please Help me with this.
Thanks in advance.
Set sound field into push notification payload https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support
I am using
Xamarin + firebase notification for cross platform app
Need
To change the default notification sound
Expect
The sound changed, even if the app is colse. Which means I will assign a different tone for the notifications which come to this app
Coding
No need to write any code to play the sound or to trigger the on notofication recieved event at all
Current result:
I success to do this with IOS only, but faild with Android.
Now I can recieve notification with custom sound even if the app is closed, without writting any code for this
My code
For IOS
1- add this line to the notification payload
"sound": "test.wav"
only sound name with the extention
2- add test.wav to IOS project under Resources as "BundleResource", or "Embedded Resource"
3- send the notification, and do not care about "NotificationRecieved" event at all
4- kill the app, and send the notification
5- notification recieved with custom sound "test.wav"
6- IOS accect "wav" or "caf" files only
For Android
Repeat the same with "wav" file, but with some changes like:
1- the sound file add at Resources/raw as AndroidResource For Project.Droid
2- try to change the payload to be:
"sound": "test.wav"
"sound": "test"
"sound": "raw/test.wav"
"sound": "raw/test"
But never success to play the sound
Question
I am sure there is something wrong in the ("sound": "test.wav") format.
I tested it with and without extention,
I do not need to handle the sound by coding, I want to assign the tone exactly as done with the IOS project
I expected IOS to be harder than Android! but at end it was easy
Any help, please?
Finally, I solved it.
For those who face the same problem I will post the solution.
For IOS, you can only pass the sound file name as I said before.
For Android, it is comples. I noticed that the app uses the default system sound for all notification which recieved in the background mode, closed, or killed app.
I went to the app settings, then I found a channel name "Miscellaneous" which used for such notifications.
The idea was how to change this channel sound?
If you create a channel with the same name, it will not work because you have to use channel name + channel ID.
I searched and finaly find the default channel id which is "fcm_fallback_notification_channel".
The second step was to create a channel with this name and id, in hope to override the system one.
I created this channel in the app start with the following code:
var importance = NotificationImportance.High;
var soundFileName = "sound";
NotificationChannel chan = new NotificationChannel("fcm_fallback_notification_channel", "Miscellaneous", importance);
chan.EnableVibration(true);
chan.LockscreenVisibility = NotificationVisibility.Public;
chan.SetSound(Android.Net.Uri.Parse("android.resource://com.myapp.test/raw/" + soundFileName), null);
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(chan);
And it works as expected :)
Now I can recieve nottifications with the custom sound even if the app is closed, killed, or background mode.
I did not think that I can do this, finally.
Thanks for everyone.
Hope this can help someone.
For the Android, you should set the sound in NotificationChannel
var channel = new NotificationChannel(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var audioattributes = new AudioAttributes.Builder();
audioattributes.SetContentType(AudioContentType.Music);
audioattributes.SetUsage(AudioUsageKind.Notification);
channel.SetSound(global::Android.Net.Uri.Parse("android.resource://" + this.ApplicationContext.PackageName + "/raw/app_sound"), audioattributes.Build());
Note: If you set it, please uninstall the app to alter sound settings, Check out these link for more details.
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 am trying to build an app which receives notification from the server. I have configured FCM with my backend server which sends out the notifications, and every notification thats being sent from the server, i receive it on my emulator.
What i am struggling to understand is how do i list all the received notifications and display them in a view.
I am imagining how whatsapp does, you get a notification and then on click of that notification, you'll be taken to that notification full view. I presume there's an onClick action or similar to achieve this, but what i am struggling to understand is how do i list all the notifications in a particular view?
Or is it like notifications are totally separate than what can be listed in a view?
If thats the case, perhaps i will have to make another api call to fetch all the notifications.
I am using FCM and now trying to make it work on Android.
Any help is appreciated.
Thanks,
Vikram
id: new Date().valueOf().toString(), // (optional for instant notification)
title: notif.fcm.title, // as FCM payload
body: notif.fcm.body, // as FCM payload (required)
sound: "bell.mp3", // "default" or filename
priority: "high", // as FCM payload
click_action: "com.myapp.package", // as FCM payload - this is used as category identifier on iOS.
badge: 10, // as FCM payload IOS only, set 0 to clear badges
number: 10, // Android only
ticker: "My Notification Ticker", // Android only
auto_cancel: true, // Android only (default true)
large_icon:
"https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg", // Android only
icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
big_text: "Show when notification is expanded", // Android only
sub_text: "This is a subText", // Android only
color: "Gray", // Android only
vibrate: 300, // Android only default: 300, no vibration if you pass 0
wake_screen: true, // Android only, wake up screen when notification arrives
group: "group", // Android only
ongoing: true, // Android only
my_custom_data: "my_custom_field_value", // extra data you want to throw
lights: true, // Android only, LED blinking (default false)
show_in_foreground: true // notification when app is in foreground (local & remote)
Above is what i use to presentLocalnotification, do you mean to say that have to use the id to display it in a view?
And how would you do it?
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.