Skip to content

Instantly share code, notes, and snippets.

@ErikDohmen
Last active November 25, 2021 14:47
Show Gist options
  • Save ErikDohmen/983adc0ad98cd62fbf61c7bf7a476078 to your computer and use it in GitHub Desktop.
Save ErikDohmen/983adc0ad98cd62fbf61c7bf7a476078 to your computer and use it in GitHub Desktop.
Creating notificationChannels and notificationChannelGroups dynamically in flutter (with custom sound)
// this could be anywhere in your flutter project files, there where you want to create the notification channels
static const platform = const MethodChannel('nl.sobit'); // use the name you have in the kotlin file as well in order to communicate with the underlaying android
// to create a notificationchannelgroup
platform.invokeMethod('createChannelGroup', {
"groupId": "1234", // id of the group
"groupName": "my group name" // name of the group
});
// to delete a notificationchannelgroup
platform.invokeMethod('deleteChannelGroup', {
"groupId": "1234", // id of the group
});
// to create a notificationchannel
platform.invokeMethod('createChannel', {
"id": "abcd", // id of the channel
"name": "my channel name", // name of the channel
"description": "a nice description", // optional description of the channel, could be empty as in ""
"sound": "plucky", // name of the sound
"groupId": "1234" // id of the notificationchannelgroup created earlier
});
// to delete a notificationchannel
// to delete a notificationchannelgroup
platform.invokeMethod('deleteChannel', {
"id": "1234", // id of the group
});
// do you have a new setup for the MainActivity.kt file with no 'onCreate' method, then use the following setup:
// At the top of the file, we need the following imports
import android.os.Build
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.MethodChannel
import android.net.Uri
import android.media.AudioAttributes
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.NotificationChannelGroup
// Within the MainActivity: FlutterActivity(){ class paste the follwing
private val CHANNEL = "nl.sobit" // replace with your own unique channel name which you set in the dart file as platform
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
// Note: this method is invoked on the main thread.
if (call.method == "createChannel") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val groupId: String? = call.argument("groupId")
val groupName: String? = call.argument("groupName")
val id: String? = call.argument("id")
val name: String? = call.argument("name")
val description: String? = call.argument("description")
val soundName: String? = call.argument("sound")
deleteChannel(id)
createGroup(groupId,groupName)
val sound = getSound(soundName)
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
val mChannel = NotificationChannel(id, name,
NotificationManager.IMPORTANCE_DEFAULT)
mChannel.setDescription(description)
mChannel.setSound(sound, audioAttributes)
mChannel.setGroup(groupId)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
result.success("Notification channel $name created")
} else {
// No-op
result.success("Android version is less than Oreo")
}
} else if(call.method == "deleteChannel") {
val id: String? = call.argument("id")
deleteChannel(id)
} else if(call.method == "deleteChannelGroup") {
val groupId: String? = call.argument("groupId")
deleteGroup(groupId)
} else if(call.method == "createChannelGroup") {
val groupId: String? = call.argument("groupId")
val groupName: String? = call.argument("groupName")
createGroup(groupId,groupName)
} else {
result.notImplemented()
}
}
}
private fun createGroup(groupId: String?, groupName: String?) { // create a channelgroup
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(groupId, groupName))
}
private fun deleteGroup(groupId: String?) { // delete a channelgroup
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.deleteNotificationChannelGroup(groupId)
}
private fun deleteChannel(id : String?){ // delete a channel
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.deleteNotificationChannel(id)
}
private fun getSound(soundName: String?) :Uri { // get the sound Uri
return when(soundName){
"concise" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.concise) // the concise file sound
"light" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.light) // the light file sound
"plucky" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.plucky) // the pluck file sound
"tasty" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.tasty) // the tasty file sound
else -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.tasty) // if the when statement couldn't find the corresponding item this one will be returned
}
// At the top of the file, we need the following imports
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import android.os.Build
import androidx.annotation.NonNull
import android.net.Uri
import android.media.AudioAttributes
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.NotificationChannelGroup
// within the onCreate method add:
MethodChannel(flutterView, "nl.sobit").setMethodCallHandler { // nl.sobit is the communication channel between flutter and kotlin and can be anything you want as long as it is unique
call, result ->
// Note: this method is invoked on the main thread.
if (call.method == "createChannel") {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val groupId: String? = call.argument("groupId") // the id of the group you want the channel to be created
val id: String? = call.argument("id") // the id of the channel
val name: String? = call.argument("name") // the name of the channel to be seen by the user within the notification settings
val description: String? = call.argument("description") // optional description to go along with the name
val soundName: String? = call.argument("sound") // reference to the file name you want to attach to the channel
deleteChannel(id) // we do this to delete the former settings in order to change the sound if needed, if there's no channel by this id, nothing will happen
val sound = getSound(soundName) // get the corresponding sound Uri, see further on in the getSound method
val audioAttributes = AudioAttributes.Builder() // declare the AudioAttributes
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
val mChannel = NotificationChannel(id, name,
NotificationManager.IMPORTANCE_DEFAULT) // create the actual channel
mChannel.setDescription(description) // add the description if set
mChannel.setSound(sound, audioAttributes) // add the sound for this channel
mChannel.setGroup(groupId) // set the group for this channel, make sure the group is created in an earlier call
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel) // attach the channel to the notificationManager
result.success("Notification channel $name with sound $soundName created") // result is given back to the flutter call
} else {
// No-op
result.success("Android version is less than Oreo")
}
} else if(call.method == "deleteChannel") {
val id: String? = call.argument("id") // get the id of the channel to be deleted
deleteChannel(id) // call the method to delete the channel
result.success("Channel with id $id deleted")
} else if(call.method == "deleteChannelGroup") {
val groupId: String? = call.argument("groupId") // id of the channelgroup to be deleted, if there are channels within this group, they will be deleted as well
deleteGroup(groupId) // call the method to delete the channelgroup
result.success("Group with id $groupId deleted")
} else if(call.method == "createChannelGroup") {
val groupId: String? = call.argument("groupId") // id of the channelgroup you want to create
val groupName: String? = call.argument("groupName") // name for the channelgroup to be seen within the notification settings
createGroup(groupId,groupName) // call the method to create the channelgroup
result.success("Group with name $groupName created") // return result
} else {
result.notImplemented()
}
}
// outside the onCreate method
private fun createGroup(groupId: String?, groupName: String?) { // create a channelgroup
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(groupId, groupName))
}
private fun deleteGroup(groupId: String?) { // delete a channelgroup
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.deleteNotificationChannelGroup(groupId)
}
private fun deleteChannel(id : String?){ // delete a channel
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.deleteNotificationChannel(id)
}
private fun getSound(soundName: String?) :Uri { // get the sound Uri
return when(soundName){
"concise" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.concise) // the concise file sound
"light" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.light) // the light file sound
"plucky" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.plucky) // the pluck file sound
"tasty" -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.tasty) // the tasty file sound
else -> Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.tasty) // if the when statement couldn't find the corresponding item this one will be returned
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment