I am using Firebase push notifications in my Android App. I can send correctly notification with custom icon, but I have not managed to play my custom sound. I always get the default sound of my device.
{
"registration_ids": "myToken",
"notification": {
"body": "my body",
"title": "my title",
"icon": "ic_notification",
"sound": "mysound.mp3" // I tried "mysound", "mysound.wav"...
},
"priority": "high"
}
The custom sound is located in /res/raw
I have been able to play my custom sound with onMessageReceived and Firebase data message but not with Firebase notification message.
My android device is Xiaomi Mi A1 and Oreo 8.1., also tried with Xiaomi Mi A2 with same result.
I tried with php and curl, with node.js... always same problem, I get my default sound.
UPDATE
With this code for node.js does not work either:
var registrationToken = 'xxxxxx';
var message = {
notification: {
title: 'my title',
body: 'my body',
},
android: {
ttl: 3600 * 1000,
notification: {
color: '#ff0000',
sound: 'mysound.mp3'
}
},
token: registrationToken
};
Finally I found the solution. For Android 8.0 and higher it's necessary to create a notification channel in your App:
NotificationChannel channel = new NotificationChannel('my_id', name, importance);
(more info: https://developer.android.com/training/notify-user/channels#java)
Then when you send the notification:
var registrationToken = 'xxxxxx';
var message = {
notification: {
title: 'my title',
body: 'my body',
},
android: {
ttl: 3600 * 1000,
notification: {
color: '#ff0000',
sound: 'mysound.mp3',
channel_id: 'my_id' // important to get custom sound
}
},
token: registrationToken
};
I was also looking for the solution to custom sound for firebase notification in the android, And I have solved this problem through Notification Channel.
I have created one notification channel with custom sound, that sound plays after receiving notification in the application background state.
You can refer following links of the notification channel.
https://medium.com/exploring-android/exploring-android-o-notification-channels-94cd274f604c
https://developer.android.com/training/notify-user/channels
You need to put your mp3 file at /res/raw/ path.
Please find the code.
NotificationManager notificationManager = (NotificationManager) getActivity().getSystemService(NotificationManager.class); // If you are writting code in fragment
OR
NotificationManager notificationManager = (NotificationManager) getSystemService(NotificationManager.class); // If you are writting code in Activity
createNotificationChannel function
private void createNotificationChannel() {
Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/" + R.raw.sample); //Here is FILE_NAME is the name of file that you want to play
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
CharSequence name = "mychannel";
String description = "testing";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
NotificationChannel channel = new NotificationChannel("cnid", name, importance);
channel.setDescription(description);
channel.enableLights(true); channel.enableVibration(true);
channel.setSound(sound, audioAttributes);
notificationManager.createNotificationChannel(channel);
}
};
createNotificationChannel();
To achieve this you need to pass android_channel_id property in the firebase notification request object.
{
"notification": {
"body": "this is testing notification",
"title": "My App",
"android_channel_id": "cnid"
},
"to": "token"
}
Note - If you create a notification channel once then you can't change the sound. You have to create a new notification channel with the new name with your desired sound.
From the documentation, include the sound in notification object under android object. Give name of the sound file in sound value. The sound files must reside in /res/raw/ . Below is a Node.js example:-
var message = {
notification: {
title: 'sample title',
body: 'Hello, its Tuesday.',
},
android: {
ttl: 3600 * 1000,
notification: {
icon: 'my_icon',
color: '#f45342',
sound: 'filename.mp3',
},
},
apns: {
payload: {
aps: {
badge: 42,
},
},
},
topic: 'industry-tech'
};
Try Enabling Sound From Firebase Console
For More Info Just Look at this answer
https://stackoverflow.com/a/44304089/9024123
may be this should be problem and also try removing '.mp3' in sound element and make it like
"sound":"mySound"
i was also facing the same issue. I always got the default sound but i fixed it as follows . I am using FCM-push (node module) https://www.npmjs.com/package/fcm-push
var message = {
to : device_token,
collapse_key : '<insert-collapse-key>',
// data : {
// '<random-data-key1>' : '<random-data-value1>',
// '<random-data-key2>' : '<random-data-value2>'
// },
notification : {
title : 'Title ',
body : 'some Body',
sound : 'notification' // my .ogg file in /res/raw
},
android: {
sound: 'notification' // my .ogg file name in /res/raw
}
};
I have not tried it with mp3 or wav and in your question it seems you have not tried with .ogg file ( though i doubt if it has anything to do with audio format but you can try)
Maybe this helps :
In my case i tried with the above approach and it did not worked, whenever i was checking in the onMessageReceived (for debug purpose) the channel id
Log.e(TAG, "Message Notification channel id: " + remoteMessage.getNotification().getChannelId());
i always got 'null'.
So reading the documentation from here https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support
I found out that i was using the wrong key for the channel id in the json.
Instead of 'channel_id' key try to use 'android_channel_id' key like this
"notification": {
"body": "Body of Your Notification",
"title": "Title of Your Notification",
"android_channel_id": "channelId",
"icon": "myIcon"
}
If i use it like that it works as expected, custom sound (from res/raw) is played
PS: in my case i set my sound on the channelId when i created it
Good luck !
One mistake I made when trying this was I didn't change the the channel id although I updated the Json and modified the code. My channel was always bound to the device sound. Just after I updated to a different channel id my code started working. Custom sound is now playing for both foreground and background
Following is the JSON which worked for me
{
"to" : "token"
,
"notification": {
"title":"Server Notification Title",
"body":"Notification Body",
"sound":"sound.wav",
"android_channel_id": "ch1"
},
"priority": "high"
}
The code
Uri soundUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/" + R.raw.sound);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "ch1")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText(remoteMessage.getNotification().getBody().toString())
.setAutoCancel(true)
.setSound(soundUri);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
if(soundUri != null){
// Changing Default mode of notification
notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
// Creating an Audio Attribute
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build();
// Creating Channel
NotificationChannel channel = new NotificationChannel("ch1","App Name",NotificationManager.IMPORTANCE_HIGH);
channel.setSound(soundUri,audioAttributes);
channel.enableLights(true); channel.enableVibration(true);
mNotificationManager.createNotificationChannel(channel);
}
}
mNotificationManager.notify(0, notificationBuilder.build());
Related
I have this code to show a notification which is working as far as to show the notification, but when i run this function again, i dont get any sound.
public NotificationManager nm;
...
void ShowNotification(string title = "", string message = "", string header = "", bool notify = false)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
CreateSilentNotificationChannel();
}
var text = GetText(Resource.String.Local_service_label);
// Set the icon, scrolling text and timestamp
var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var msSinceEpoch = (long)sinceEpoch.TotalMilliseconds;
PendingIntent contentIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0);
PendingIntent refreshIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(LocalService)), 0);
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, currentNotId);
builder.SetContentTitle(GetString(Resource.String.OddEven_Notifications_AlertTitle))
.SetContentIntent(contentIntent)
.SetSmallIcon(Resource.Mipmap.ic_launcher)
.SetTicker(text)
.SetWhen(msSinceEpoch)
.SetAutoCancel(false)
.SetOngoing(true)
.SetUsesChronometer(true)
.SetShowWhen(true)
.SetContentTitle(title)
.SetVisibility((int)NotificationVisibility.Public)
.SetSubText(header)
.SetLargeIcon(BitmapFactory.DecodeResource(this.Resources, Resource.Mipmap.ic_launcher))
.SetContentText(message);
if (notify)
{
builder.SetVibrate(new long[] { 0, 400, 200, 200 });
builder.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));
}
StickyNotification = builder.Build();
if (Build.VERSION.SdkInt < BuildVersionCodes.O && notify)
{
StickyNotification.Vibrate = new long[] { 0, 400, 200, 200 };
}
nm.Notify(NOTIFICATION, StickyNotification);
}
private void CreateSilentNotificationChannel()
{
var channelDescription = "SilentChannelForOddEvenNotification";
var chan1 = new NotificationChannel(notIDSilent, GetString(Resource.String.app_name), NotificationImportance.High)
{
Description = channelDescription,
Name = GetString(Resource.String.app_name),
};
// set the channel properties
chan1.EnableLights(true);
chan1.LightColor = Color.Red;
chan1.SetSound(null, null);
chan1.EnableVibration(false);
chan1.SetBypassDnd(true);
chan1.LockscreenVisibility = NotificationVisibility.Public;
// finally create the notification channel
//var manager = (NotificationManager)GetSystemService(NotificationService);
nm.CreateNotificationChannel(chan1);
}
i'm running the function ShowNotification() every 5 minutes but if i have the property notify true or false, i don't get any sound, why?
What is the proper way to have a sticky notification that we update regularly and sometimes we want to also have sound?
In the notification payload of the notification there is a sound key.
From the official documentation its use is:
Indicates a sound to play when the device receives a notification. Supports default or the filename of a sound resource bundled in the app. Sound files must reside in /res/raw/anySound.
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon",
"sound" : "default"
}
}
In the notification payload either you can use "sound" : "default" OR "sound" : "anySound"
In your case might be these lines are problematic
chan1.SetSound(null, null);
if (notify){
builder.SetVibrate(new long[] { 0, 400, 200, 200 });
builder.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));
}
Beginning with Android 8.0 (Oreo), it would better to set the sound or the proority in Channel. And use the two ways below instead of chan1.SetSound(null, null);.
Use the specific ringtone for notification.
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var channel = new NotificationChannel(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
channel.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Ringtone),alarmAttributes);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
For more details, please refer to the link below. specific ringtone firebase notification xamarin.android
Use the custom sound for notification.
void CreateNotificationChannel1()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var path = Android.Net.Uri.Parse("android.resource://com.companyname.NotificationChannelsDemo/" + Resource.Raw.Hello);
var name = Resources.GetString(Resource.String.channel_name);
var description = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID1, name, NotificationImportance.Max)
{
Description = description
};
channel.SetSound(path, alarmAttributes);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
For more info, please check the link below. Custom Notification Sound FireBase
Local notifications pop up when my Xamarin phone app receives a new event. This works fine, and it also plays a sound. However I want to play different sounds depending on the type of event that my app has received. I thought this would be simple enough, but whatever sound is played first after I rebuild the app, that is the sound that then plays for every notification regardless of the code.
For example, after rebuild, if Priority enum is Priority.Temp then TempNotif.wav will play. But if the code calls this method again to show another notification and Priority enum isn't Priority.Temp, TempNotif.wav still plays, even though I have set it to play StandardNotif.wav. It seems like android takes a copy of the first sound and doesn't bother updating it once there is a sound in place. Whatever is happening, surely I can play different sounds for different notifcations?
Here is code:
public void CreateNotification(string title, string message, Priority priority)
{
Android.Net.Uri sound = null;
if (priority == Priority.Temperature)
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
builder = new NotificationCompat.Builder(context, notificationChannelId);
builder.SetContentTitle(title)
.SetAutoCancel(true)
.SetContentText(message)
.SetPriority((int)NotificationPriority.High)
.SetSmallIcon(Resource.Drawable.MetroIcon)
.SetColor(00255)
.SetVibrate(new long[0])
.SetSound(sound)
.SetVisibility((int)NotificationVisibility.Public);
notificationManager = context.GetSystemService(Context.NotificationService) as
NotificationManager;
if (global::Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
NotificationImportance importance = NotificationImportance.High;
NotificationChannel notificationChannel = new NotificationChannel(notificationChannelId,
title, importance);
notificationChannel.Importance = NotificationImportance.High;
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetSound(sound, alarmAttributes);
notificationChannel.SetShowBadge(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
if (notificationManager != null)
{
builder.SetChannelId(notificationChannelId);
notificationManager.CreateNotificationChannel(notificationChannel);
}
}
notificationManager.Notify(0, builder.Build());
}
Credit to #Mooniean for the answer!
The answer is to provide a different channel ID for each type of notification I want to display.
I set two static values for channel ID's and provide one depending on the type of notification I want to display.
private static string StandardchannelId = "1000";
private static string TempChannelId = "2000";
Here I assign my channelID depending on an enum I made:
if (priority == Priority.Temperature)
{
this.channelId = TempChannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
this.channelId = StandardchannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
And here I assign the channelID:
builder.SetChannelId(this.channelId);
i have a { N } app that should trigger notifications.
i'm using the notificationChannel but i keep getting the same error when the app crushed.
"System.err: TypeError: android.NotificationChannel is not a constructor"
my code is :
android.app.job.JobService.extend("com.tns.notifications.MyJobService", {
onStartJob: function(params) {
console.log("Job execution ...");
// Do something useful here, fetch data and show notification for example
var utils = require("utils/utils");
var context = utils.ad.getApplicationContext();
// var res=GeofenceService.mainFunction()
// console.log("res",res)
var builder = new android.app.Notification.Builder(context);
builder.setContentTitle("Scheduled Notification")
.setAutoCancel(true)
.setColor(android.R.color.holo_purple)//getResources().getColor(R.color.colorAccent))
.setContentText("This notification has been triggered by Notification Service")
.setVibrate([100, 200, 100])
.setSmallIcon(android.R.drawable.btn_star_big_on);
// will open main NativeScript activity when the notification is pressed
var mainIntent = new android.content.Intent(context, com.tns.NativeScriptActivity.class);
var mNotificationManager = context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
// The id of the channel.
const channelId = "my_channel_01";
// The user-visible name of the channel.
const name = "Channel name";
// The user-visible description of the channel.
const description = "Channel description";
const importance = android.app.NotificationManager.IMPORTANCE_LOW;
const mChannel = new android.app.NotificationChannel(channelId, name,importance);
// Configure the notification channel.
mChannel.setDescription(description);
mChannel.enableLights(true);
// Sets the notification light color for notifications posted to this
// channel, if the device supports this feature.
mChannel.setLightColor(android.graphics.Color.RED);
mChannel.enableVibration(true);
mNotificationManager.createNotificationChannel(mChannel);
builder.setChannelId(channelId);
mNotificationManager.notify(1, builder.build());
return false;
},
onStopJob: function() {
console.log("Stopping job ...");
}
});
the error coming from this row :
const mChannel = new android.app.NotificationChannel(channelId, name,importance);
why is he telling me that NotificationChannel is not a constructor?
what did i missed ?
this is where i got this code and it seems to work for other people.
https://github.com/NativeScript/sample-android-background-services
Edit:
i just checked my API Level and its 26 so even with the if statement before the channel line its crushing.
when im looking at my platforms folder in the android manifest i see this :
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="25"/>
why its 25 ?
android.app.NotificationChannel is available only on API Level 26 and above (Android 8.0 - Oreo). If you are using an earlier version, it will throw that error.
You must check the version before you access those apis, something like
if (android.os.Build.VERSION.SDK_INT >= 26) {
const mChannel = new android.app.NotificationChannel(channelId, name,importance);
}
Update:
You must set your target SDK to a higher version, at least 26. You will not be even able to upload your APK to Google Play if you are targeting a lower version since August 2018.
When multiple mails arrive one by one, Gmail groups them and shows only one notification message on the Notification Area. I would like to do the same thing. I searched Google and found that I need to set tag, but setting the same tag just replaced the previous one, not showing multiple messages as Gmail.
Should I not use the notification-type, but use the data-type only and handle notifications myself? If so, this should be something a lot of people are ding. Is there a sample project that I can start with?
Also, if I can somehow use the notification-type for grouping, it gives the data as Intent extras. How does it pass multiple data to my activity, if the notification is showing multiple items as Gmail?
{
"to": "/topics/that",
"notification": {
"title": "Title 686",
"body": "My body",
"tag": "xxx"
},
"data": {
"title": "Title 686",
"body": "My body",
}
}
You can use inbox style with notification builder
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_glyph)
.setContentTitle(title)
.setColor(context.getResources().getColor(R.color.colorPrimary))
.setContentText(contentText);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
for (int i = 1; i < 11; i++) {
inboxStyle.addLine(("Message " + i);
}
inboxStyle.setBigContentTitle(title);
mBuilder.setStyle(inboxStyle);
I'm sending notifications to an android device using node-gcm, and in some cases, I need to send an image with the notification to display as a thumbnail, like so:
notification with thumbnail
And sometimes I need to send notifications without the thumbnail. With the below code I can send the image in the notification, the problem is when another notification is received, they collapse, making the new one overwriting a notification that was already there:
var message = new gcm.Message({
"data" : {
"title" : "Test",
"message" : "Test message!",
"priority" : 2, // Highest priority.
"ledColor" : [255, 0, 0, 1],
"content-available": "1",
"image": req.body.notificationImageUrl, //<-- image URL
},
});
But if I set up the message like below, I can't find a way to send the image but the notifications do not collapse and all of them appear. Another problem is that the led does not activate in this version:
var message = new gcm.Message({
data: {
"priority" : 2, // Highest priority.
"content-available": "1",
"image": req.body.notificationImageUrl, // <-- image URL
},
notification:{
title: "Test",
body: "Test message!",
color: "#892121",
sound: 'default',
vibrationPattern: [300, 150, 300], // Vibrate for 300ms then wait 150ms and then vibrate for 300ms.
ledColor: [255, 0, 0, 1], // <-- this does not work
},
});
What I want is a way to send the notification with the thumbnail in a way that it does not overwrite a notification that was previously there.
EDIT: I forgot to mention, im using Ionic Framework with Cordova so I can't manage the notifications in the device unless there is a way to do it through those frameworks.
Thanks in advance!
While going through the node-gcm issues I found the solution, there is a parameter called "notId" to add a ID to a notification.
var message = new gcm.Message({
"data": {
"title": "Test",
"message": "Test message!",
"priority": 2, // Highest priority.
"ledColor": [255, 0, 0, 1],
"content-available": "1",
"image": req.body.notificationImageUrl,
"notId": parseInt(Math.random() * new Date().getSeconds(), 10), // <-- this solved the problem
},
});
The management of the display of notifications is done on the device. You have to make sure you are setting, on Android, a different NOTIFICATION_ID for each notification, or the last one will always replace the one before it.
// Sets an ID for the notification - make sure to change this for different notifications
int mNotificationId = 001;
// Gets an instance of the NotificationManager service
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it
mNotifyMgr.notify(mNotificationId, mBuilder.build());