Simplify Creating Notifications In Android Compose
Simplified way to create notifications in Android Compose with custom method.

In this post I will show you a class I created to simplify the process of creating and showing notifications in Android Compose.

I wanted to create a simplified way to create and send notifications in Android by building a class to implement this functionality. This example just shows a single notification that will disappear when the user clicks it. You can attach an Intent to the PendingIntent to navigate the user to some activity in your app.

Setup

One of the first things you will need is to add the POST_NOTIFICATION permission and supply a way to get permission from the user. Luckily I just created and posted a simplified way to do this. Just visit the link below.

Android Compose Requesting Multiple Permissions with Custom Message

or

Android Compose Streamline Requesting Permissions With Example

Now you have a method for requesting the needed permission, lets get started.

Code

This is the project structure. I created a package of the main named notification just to keep things clean.

Image displaying the Android project structure.

AndroidManifest.xml

In the AndroidManifest.xml, add the POST_NOTIFICATION permission

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

MainActivity

In the MainActivity, lets create the notification. This is how to access my custom function. The function takes generic values that you can create.

MyNotificationBuilder.create(
                                        applicationContext,
                                        resources.getInteger(R.integer.default_notification_id),
                                        "test_channel",
                                        "Hello!",
                                        "I want to send you a message!",
                                        "Channel Name",
                                        "Channel Description",
                                        NotificationManager.IMPORTANCE_DEFAULT
                                    )

integers.xml

Create a resource named default_notification_id. This is located in a new file named integers.xml I created in the res/values folder.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="default_notification_id">1234</integer>
</resources>

-test_channel is the channel_id

-Channel Name is the name of the channel you are creating. This will be displayed to the user when they access the app settings and view the notification panel of your app.

-Channel Description is the description of the channel. This will be displayed to the user when they access the app settings and view the notification panel of your app.

MainActivity

This is the full MainActivity, this also shows the permission function I created from the links above as well.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            SamplePermissionsTheme {
                val permissionState = remember {
                    mutableStateListOf(
                        RequestingPermission(
                            false,
                            permissionName = Manifest.permission.POST_NOTIFICATIONS,
                            message = "Please approve permission in order to receive notifications."
                        )
                    )

                }

                Scaffold(modifier = Modifier.fillMaxSize(), topBar = {
                    MyPermissionState(
                        permissionState,
                        permissionChanged = { index, isGranted ->
                            val sample = permissionState[index]
                            sample.isGranted = isGranted
                            permissionState.removeAt(index)
                            permissionState.add(index, sample)
                        },
                        rationalChanged = { index, showRational ->
                            val sample = permissionState[index]
                            sample.showRational = showRational
                            permissionState.removeAt(index)
                            permissionState.add(index, sample)
                        }
                    )
                }) { innerPadding ->
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(innerPadding)
                            .background(Color.Black),
                        horizontalAlignment = Alignment.CenterHorizontally,
                        verticalArrangement = Arrangement.Center
                    ) {
                        permissionState.forEach { requestingPermission ->
                            Text(
                                text = "${requestingPermission.permissionName}\nMessage = \n${if (requestingPermission.isGranted) "Permission Granted" else "Permission Denied"}",
                                color = if (requestingPermission.isGranted) Color.Green else Color.Red
                            )
                        }
                        Row(
                            modifier = Modifier.padding(20.dp),
                            horizontalArrangement = Arrangement.Center
                        ) {
                            ElevatedButton(
                                modifier = Modifier
                                    .padding(20.dp)
                                    .focusable(permissionState[0].isGranted)
                                    .align(Alignment.CenterVertically), onClick = {
                                    MyNotificationBuilder.create(
                                        applicationContext,
                                        resources.getInteger(R.integer.default_notification_id),
                                        "test_channel",
                                        "Hello!",
                                        "I want to send you a message!",
                                        "Channel Name",
                                        "Channel Description",
                                        NotificationManager.IMPORTANCE_DEFAULT
                                    )
                                }) {
                                Text(text = if (permissionState[0].isGranted) "Click to Receive a notification" else "Please enable notification permission")
                            }
                        }
                    }

                }
            }
        }
    }
}

MyNotificationBuilder

Now create the custom notification object. If you wanted to direct the user to a certain activity in your app, then update the Intent() reference in the PendingIntent to include your activity.

Breakdown

contextApplication context
notifyIDdefault_notification_id created in integers.xml above
channelIDName of the notification channel
titleString of notification title
contentString of notification message
channelNameName of the channel
channelDescDescription of the channel
importanceINT used to set notification importance. Use NotificationManager.<importance>
object MyNotificationBuilder {

    fun create(
        context: Context,
        notifyID : Int,
        channelId: String,
        title: String,
        content: String,
        channelName: String,
        channelDesc: String,
        importance: Int
    ) {
        val notificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notificationManager.createNotificationChannel(
                createNotificationChannel(
                    channelId,
                    channelName,
                    channelDesc,
                    importance
                )
            )
        }
        val pendingIntent: PendingIntent =
            PendingIntent.getActivity(context, 0, Intent(), PendingIntent.FLAG_IMMUTABLE)

        val builder = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(title)
            .setContentText(content)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
        notificationManager.notify(notifyID, builder.build())
    }

    @SuppressLint("NewApi")
    private fun createNotificationChannel(
        channelId: String,
        channelName: String,
        channelDesc: String,
        importance: Int
    ): NotificationChannel {
        val channel = NotificationChannel(channelId, channelName, importance).apply {
            description = channelDesc
        }
        return channel
    }
}

I hope this was useful.

Leave a Reply

Your email address will not be published. Required fields are marked *