I am trying to customize notification sound of firebase_messaging in flutter. On foreground I am implementing flutter_local_notifications package to deliver notification where I have setup custom sound and vibration. But in case of background, notification is handled by default notification channel. Is there any way I can create a notification channel or use the one I just created using flutter_local_notifications package?
4 Answers
For those of you arriving here because your FCM messages aren't acting as you prefer while your app is in the background:
You will probably need to create a Notification Channel if you want a "heads-up" notification when the app is in the background and you want to have your own custom sound accompanying it. The default Notification Channel used by the FCM does not have the "pop on screen" setting enabled and uses the default system sound. You can see this by going to the app's settings on your device.
OP is using the flutter_local_notifications package, which is pretty much the "go-to" package for notification handling in flutter. You can create your own Notification Channels via the createNotificationChannel
method and assign your desired parameters (including sound and priority level). This is the quick and easier way of getting your notifications to act as you want them.
If you want to create your own Notification Channel without the flutter_local_notifications package, then you will have to modify your MainActivity.kt
(or Java) file in its native form. It's not overly complicated, but it is more low-level than just using the flutter_local_notifications package. This Medium post describes how to do that (for Android).

- 6,072
- 5
- 31
- 43
-
1any ideas for ios? – Shalabyer Jan 27 '21 at 04:37
-
1@Shalabyer this Q/A should help with that -- it's how I got mine set up: https://stackoverflow.com/questions/54002617/custom-sound-push-notification-does-not-work-flutter/63922550#63922550 – Sludge Jan 27 '21 at 14:18
-
Thanks for your reply, I will definitely try it. – Shalabyer Jan 27 '21 at 17:45
-
I just revied that Q/A and it seemed to me that it will only work in the foreground, as in the answers he didn't create a notification channel, and we need a notification channel to make a custom sound in the background am I getting it right? – Shalabyer Feb 07 '21 at 21:37
-
1@Shalabyer You don't make a notification channel on iOS as you do on Android -- did you follow the instructions in that Q/A where you add the asset to your bundle? You may need to tinker with your JSON payload, it took some trial and error for me to get it and unfortunately I don't have it in front of me right now to give to you. Perhaps this Q/A will guide you? https://stackoverflow.com/questions/41562823/fcm-remote-notifications-payload-for-ios-and-android – Sludge Feb 08 '21 at 15:36
-
Thank you man, I will definitely try this, these provided info were very helpful :) – Shalabyer Feb 08 '21 at 20:26
In Flutter you can create android notification channel yourself thru MainActivity.kt or MainActivity.java file depending whichever you have in your project Android folder. Good guide here - using MainActivity.kt which is easy and working, tried myself - it works:
package com.example.new_channel //Your own package name
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.net.Uri;
import android.media.AudioAttributes;
import android.content.ContentResolver;
class MainActivity: FlutterActivity() {
private val CHANNEL = "somethinguniqueforyou.com/channel_test" //The channel name you set in your main.dart file
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
if (call.method == "createNotificationChannel"){
val argData = call.arguments as java.util.HashMap<String, String>
val completed = createNotificationChannel(argData)
if (completed == true){
result.success(completed)
}
else{
result.error("Error Code", "Error Message", null)
}
} else {
result.notImplemented()
}
}
}
private fun createNotificationChannel(mapData: HashMap<String,String>): Boolean {
val completed: Boolean
if (VERSION.SDK_INT >= VERSION_CODES.O) {
// Create the NotificationChannel
val id = mapData["id"]
val name = mapData["name"]
val descriptionText = mapData["description"]
val sound = "your_sweet_sound"
val importance = NotificationManager.IMPORTANCE_HIGH
val mChannel = NotificationChannel(id, name, importance)
mChannel.description = descriptionText
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"+ getApplicationContext().getPackageName() + "/raw/your_sweet_sound");
val att = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build();
mChannel.setSound(soundUri, att)
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
completed = true
}
else{
completed = false
}
return completed
}
}
And this is with MainActivity java:
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.media.AudioAttributes;
import androidx.core.app.NotificationCompat;
import android.net.Uri;
import android.content.ContentResolver;
this is a code
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(“new_email_arrived_channel”, “My Emailer”, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setShowBadge(true);
notificationChannel.setDescription(“”);
AudioAttributes att = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build();
notificationChannel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + “://” + getPackageName() + “/raw/bell”), att);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{400, 400});
notificationChannel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(notificationChannel);
}
In Flutter side you may need trigger for initiating the process and naming the notification channel. It is from the same source above:
String _statusText = "Waiting...";
final String _finished = "Finished creating channel";
final String _error = "Error while creating channel";
static const MethodChannel _channel =
MethodChannel('somethinguniqueforyou.com/channel_test');
Map<String, String> channelMap = {
"id": "CHAT_MESSAGES",
"name": "Chats",
"description": "Chat notifications",
};
void _createNewChannel() async {
try {
await _channel.invokeMethod('createNotificationChannel', channelMap);
setState(() {
_statusText = _finished;
});
} on PlatformException catch (e) {
_statusText = _error;
print(e);
}
}
Now for all Android versions you need only this format notification payload:
"notification": {
"body": "Test notification",
"title": "Test Test Test",
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"sound": "your_custom_sound"
"android_channel_id": "channel_id_youcreated",
},
'to':
"",
},
Sound file name is not necessary in the above given notification payload if you assigned that sound to your notification channel thru MainActivity.kt or java file. However, it is necessary for older Android versions as they will use the sound file directly.

- 2,235
- 24
- 22
If you check in the Firebase Console, when sending the notification, you can especify a channel ID in "other options", there you can write the channel you have already created using flutter_local_notifications.
Hope this helps!

- 973
- 4
- 10
Since you are already using flutter_local_notifications
there is an alternate way to the implementation mentioned by @Elmar for Android.
As per the FCM Legacy API Doc
The notification's channel id (new in Android O).
The app must create a channel with this channel ID before any notification with this channel ID is received.
If you don't send this channel ID in the request, or if the channel ID provided has not yet been created by the app, FCM uses the channel ID specified in the app manifest.
Step 1: Define android notification channel
/// The plugin
FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin;
/// File name should not have the extension
static const String soundFileName = 'file_name_of_sound';
/// Custom notification channel
final channel = const AndroidNotificationChannel(
'custom_notification_channel_01',
'Notification channel with custom sound notifications',
description: 'This channel is used for notifications with a custom sound.',
importance: Importance.high,
playSound: true,
sound: RawResourceAndroidNotificationSound(soundFileName),
);
Step 2: Create notification channel, this should be done early in the code, preferrably where the FirebaseMessaging
is initialized
await flutterLocalNotificationsPlugin
?.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
Step 3: Include the android channel id in push notification from the backend.
Now you are good to go, test this one locally using postman or a client of your choice.
METHOD: POST
URL: https://fcm.googleapis.com/fcm/send
HEADER: Don't forget to add Authorization=key=${server_key_from_firebase_console}
BODY:
{
"to": "fcm_token",
"notification": {
"android_channel_id": "custom_notification_channel_01",
"title": "Title of the custom notification",
"body": "An important notification with a custom sound",
"sound": "custom_sound_file_name"
}
}
PS: The sound is optional, if you have multiple custom sounds, enable the play sound in the channel and include the file name of the custom sound in the notification payload.

- 10,211
- 2
- 35
- 60