If you are having issues with trying to customize your notifications in Flutter on Android, you may need to create your own Notification Channel to get it working as you imagined. The documentation on how to do this is about none, so hopefully this guide will assist you.
If your problem is with playing sound or showing a “heads-up” display notification while your app is in the background, it may be due to the default Notification Channel settings created by Flutter. To bypass this, you must create your own channel. Further, it’s a good idea to have your own channels with your own specifications anyway.
This task is not particularly difficult; however, if this is your first stop on trying to get your notifications to work, I recommend you see if any of the following two scenarios apply to you:
- Firebase Cloud Messaging (FCM) — If you are using FCM to send notifications and are having issues with the “heads-up” displays and sounds for notifications (while the app is in the background), this is because the default Notification Channel may not be set to show them. To find out if this is your problem: Go to your app’s info page (hold down your app icon and tap “App info”, then tap “Notifications” -> “Miscellaneous” -> “Advanced” ). You may see that “Pop on screen” is turned off and that “Sound” says “Default notification sound” [see image below]. This is possibly your problem because your message is being sent through this Notification Channel (“Miscellaneous”). You can turn on “Pop on screen” manually and the “heads-up” notifications should appear while the app is in the background, but once you uninstall and reinstall or clear the data, that setting will be reset. If you need it to be set on install and persist, then continue with the article. We will be creating our own channel to have FCM send the messages through, where we will set our own parameters to show and play what we want.
2. flutter_local_notifications — This is the “go-to” package for handling notifications in a Flutter application. It can create Notification Channels for you and the example in the GitHub page demonstrates almost every scenario you may need. If you are looking for a pretty quick implementation, this may be your best option and there’s no need to continue with this article.
If you still need to create your own Notification Channel, continue on and we will get this running in (almost) no time. We will make this channel in the default Flutter application and only have to modify main.dart
and MainActivity.kt
.
We will create the Notification Channel on button press; however, if you are just trying to establish a channel for your app to use, you will probably want to set this up during initialization.
1. Create a new Flutter application in the IDE of your choice (if you are looking to make your own Notification Channels, I assume you already know how to create a basic project)
2. In your Main.dart file, delete everything and replace it with this:
It won’t do anything right now except change the _statusText
if you tap the button.
Now that we are on the same page, we can start setting this up. We will start with the Flutter-side code, which only consists of three steps.
Flutter Code
In order to set up Notification Channels, we have to have our Flutter code contact the Android native code (Kotlin or Java, depending on your setup). This is done via MethodChannel
.
- Create a
MethodChannel
instance in your_MyHomePageState
like so:
static const MethodChannel _channel =MethodChannel('somethinguniqueforyou.com/channel_test');
Per Flutter docs: “The client and host sides of a channel are connected through a channel name passed in the channel constructor. All channel names used in a single app must be unique; prefix the channel name with a unique ‘domain prefix’. So make the ‘somethinguniqueforyou…’ relevant to you.
The MethodChannel
class is brought in via the services.dart
import.
2. Create a map of parameters in your _MyHomePageState
that we will use to create the Notification Channel:
Map<String, String> channelMap = {"id": "CHAT_MESSAGES","name": "Chats","description": "Chat notifications",};
The “id” will be used by FCM (or other messaging service) to send messages to that specific Notification Channel with that channel’s settings (such as custom sound, lights, etc.).
The “name” is what the Notification Channel will be named in the app’s notification settings. The end-user will see this in their app settings.
The “description” is what the channel’s description will be in the app’s notification settings. The end-user will see this in their app settings.
3. Call invokeMethod
on the MethodCall
and send the data:
We will be jumping ahead for a second by doing this, but it’ll make sense once we move to the Kotlin side of things. Within the _createNewChannel
method, we will add the following:
try { await _channel.invokeMethod('createNotificationChannel', channelMap); setState(() { _statusText = _finished; });} on PlatformException catch (e) { _statusText = _error; print(e);}
We are calling our MethodChannel
and sending two arguments, ‘createNotificationChannel’ and our map ‘channelMap’. We know what the latter is, as we just created it, but we will get to the former next.
If we succeed or fail to create the Notification Channel, the _statusText
will be updated accordingly.
We are done with the Flutter side and this is our Main.dart
file:
Now, let’s move on to the Kotlin side of things.
Kotlin Code
- Find your
MainActivity.kt
file and open it. It will be located atandroid/app/src/main/kotlin
If you have aMainActivity.java
instead, follow the syntax here. - For sake of brevity and formatting, I will post the finished
MainActivity.kt
file and explain it from there:
A few things to note:
- Don’t forget to have your own package name at the top. It’s already set for you when you create the project.
- The
CHANNEL
value has to be the same you made in themain.dart
file. - You will see a sound file value (“your_sweet_sound”) and everything relating to setting it up. If you want to follow along to this, find a small .wav file and add it to the
android/app/src/res/raw
directory. If thatraw
directory doesn’t exist, create it. If you don’t need sound, just comment outsound
,soundUri
,mChannel.setSound
, andatt
What happens:
- Our
main.dart
file calls this viainvokeMethod
and passes ‘createNotificationChannel’ and our channelMap containing our data to complete the Notification Channel’s metadata. - If the
call.method
equals ‘createNotificationChannel’ (which it will in this case), it takes the channelMap and casts it as a HashMap to ourcreateNotificationChannel
method. - In the
createNotificationChannel
method, we are parsing the channelMap (now called ‘mapData’) data into their own values. - We create an
importance
value and set it to IMPORTANCE_HIGH. This is the key factor in making the channel allow the “heads-up” display by default. - We assign our parsed ‘mapData’ values to
mChannel
and callnotificationManager.createNotificationChannel
to create it. - If it succeeds, we return true — if not, we return false.
We’re done. Now stop the app, restart it, and head back to your main.dart
file and tap on the FloatingActionButton.
Hopefully your status text changes to “Finished creating channel.” If so, head out of your app and go to its notification settings (hold the app icon -> App info -> Notifications). You should now see a new channel with the name you assigned it (in my case “Chats”). When you tap on it, you should see that “Pop on screen” is on by default, it says “app provided sound”, and the description at the bottom should say whatever you provided (in my case “Chat notifications”).
Obviously there are many different settings to play around with but hopefully this can get you started in the right direction.
Remember, you must use the Channel ID to direct the notifications from your messaging service. You will also have to set up the Notification Channel before you send a message to it.
If you plan on changing details about a Notification Channel you already set, you will have to uninstall/reinstall the app first.
Contact me with any questions or issues with this.
Edit: If you’re wondering about whether or not you have to check if the Notification Channel exists first, you do not. The docs state:
Creating an existing notification channel with its original values performs no operation, so it’s safe to call this code when starting an app.
See the following for more information on everything you need to set your Notification Channels: