
In this article, we’ll learn how to implement the different notification styles in Android.
Prerequisites:
We’ll look at the following styles:
First, create an Android Studio project. Add a class called MyNotifications and paste the following code.
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.os.Build
import androidx.core.app.NotificationCompat
import kotlin.concurrent.thread
class MyNotifications(private val context: Context) {
private val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val exampleChannelID = "EXAMPLE_CHANNEL"
companion object {
const val exampleNotificationID = 1
}
init {
createNotificationChannel()
}
fun postNotification() {
val notificationBuilder = getNotificationBuilder()
// set the title and body text
notificationBuilder.setContentTitle("Notification Title")
notificationBuilder.setContentText("Notification Message")
// post the notification
notificationManager.notify(exampleNotificationID, notificationBuilder.build())
}
private fun getNotificationBuilder(): NotificationCompat.Builder {
// this intent opens the MainActivity when the user taps on the notification
val intentNotification = Intent(context, MainActivity::class.java)
val pendingIntentNotification = PendingIntent.getActivity(
context,
exampleNotificationID,
intentNotification,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val builder = NotificationCompat.Builder(context.applicationContext, exampleChannelID)
.setSmallIcon(R.drawable.chair)
.setContentIntent(pendingIntentNotification)
.setAutoCancel(false)
.setStyle(NotificationCompat.BigTextStyle())
.setOnlyAlertOnce(true)
.setDefaults(NotificationCompat.DEFAULT_ALL) // For backward compatibility
.setPriority(NotificationManager.IMPORTANCE_HIGH) // for backward compatibility
return builder
}
private fun createNotificationChannel() {
// check the Android 8.0 (API level 26) version
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Channel name"
val descriptionText = "Channel description"
val importance = NotificationManager.IMPORTANCE_HIGH
val exampleChannel = NotificationChannel(exampleChannelID, name, importance)
exampleChannel.description = descriptionText
exampleChannel.enableVibration(true)
exampleChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
// Register the channel with the system.
// You can't change the importance or other notification behaviors after this.
notificationManager.createNotificationChannel(exampleChannel)
}
}
}
It contains all the necessary methods to create and post the notification. Next, in the Manifest file, add the notification permission. We need it for the devices running Android 13 and above.
<manifest ...>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
In the MainActivity, add the following code:
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
class MainActivity : ComponentActivity() {
private lateinit var myNotifications: MyNotifications
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme {
val context = LocalContext.current
myNotifications = MyNotifications(context)
var permissionGranted by remember {
mutableStateOf(isPermissionGranted())
}
val permissionLauncher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) { permissionGranted_ ->
// this is called when the user selects allow or deny
permissionGranted = permissionGranted_
}
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
if (permissionGranted) {
Button(
onClick = {
myNotifications.postNotification()
}
) {
Text(text = "Show Notification")
}
} else {
Button(
onClick = {
// ask for permission
// isPermissionGranted() returns true if the device is running 12 and below
// I added this condition to remove the warning
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
}
}
) {
Text(text = "Enable Permission")
}
}
}
}
}
}
}
private fun isPermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
} else {
true
}
}
}
We created buttons to ask the permission and post the notification. Run the project. In Android 13, the output looks like this:

It’s a basic notification. Let’s add some styles.
1. Action Buttons:
Before adding buttons to the notification, we should create a broadcast receiver. Click on the File > New > Other > Broadcast receiver.

Type MyReceiver in the name field and click on the Finish button.

We add buttons while creating the notification builder. A notification can hold a maximum of 3 buttons.
private fun getNotificationBuilder(): NotificationCompat.Builder {
// this intent opens the MainActivity when the user taps on the notification
val intentNotification = Intent(context, MainActivity::class.java)
val pendingIntentNotification = PendingIntent.getActivity(
context,
exampleNotificationID,
intentNotification,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
// remind later button click
val remindLaterIntent = Intent(context, MyReceiver::class.java)
remindLaterIntent.putExtra("NOTIFICATION_BUTTON_CLICK", "REMIND_LATER_CLICK")
val remindLaterPendingIntent: PendingIntent =
PendingIntent.getBroadcast(
context,
0,
remindLaterIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val builder = NotificationCompat.Builder(context.applicationContext, exampleChannelID)
.setSmallIcon(R.drawable.chair)
.setContentIntent(pendingIntentNotification)
.setAutoCancel(false)
.setStyle(NotificationCompat.BigTextStyle())
.setOnlyAlertOnce(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.addAction(R.drawable.chair, "REMIND LATER", remindLaterPendingIntent) // add the intent
return builder
}
The addAction() method adds the action button to the notification. It takes 3 parameters:
public @NonNull NotificationCompat.Builder addAction(
int icon,
@Nullable CharSequence title,
@Nullable PendingIntent intent
)
- icon – Resource ID of a drawable that represents the action.
- title – Title of the button.
- intent – The intent to be fired when the users tap on the button.
In the broadcast receiver, paste the following code:
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// This method is called when the BroadcastReceiver is receiving an Intent broadcast.
val buttonClick = intent.getStringExtra("NOTIFICATION_BUTTON_CLICK")
if (buttonClick == "REMIND_LATER_CLICK") {
Toast.makeText(context.applicationContext, "Remind later button click", Toast.LENGTH_SHORT).show()
// cancel the notification
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(MyNotifications.exampleNotificationID)
}
}
}
The onReceive() gets called when the users tap on the button. Here, we are showing a toast message.
Run the project. The output looks like this:

2. Progressbar:
Notifications can display an animated progress indicator to show users the status of an ongoing task.
In the MyNotifications, change the postNotification() method:
fun postNotification() {
val notificationBuilder = getNotificationBuilder()
val maxProgress = 100
var currentProgress = 0
// Issue the initial notification with zero progress
setProgress(notificationBuilder, maxProgress, currentProgress)
thread {
while (currentProgress <= maxProgress) {
Thread.sleep(500)
currentProgress += 20
setProgress(notificationBuilder, maxProgress, currentProgress)
}
// remove the progress bar and show the download complete message
notificationBuilder.setContentText("Download complete")
setProgress(notificationBuilder, 0, 0)
}
}
private fun setProgress(notificationBuilder: NotificationCompat.Builder, maxProgress: Int, currentProgress: Int) {
notificationBuilder.setProgress(maxProgress, currentProgress, false)
notificationManager.notify(exampleNotificationID, notificationBuilder.build())
}
Output:

The notificationBuilder.setProgress() displays the progress indicator.
public @NonNull NotificationCompat.Builder setProgress(int max, int progress, boolean indeterminate)
- max – The maximum values of the progress (such as 100)
- progress – The current progress
- indeterminate – If the progressbar is indeterminate (link here)
We should call the method continuously with an updated progress value and re-issue the notification.
To remove the progress bar, call setProgress(0, 0, false).
3. Large Image:
Let’s display this dog on the notification. First, download the image and put it in the drawable folder. To add it to the notification, use the setStyle() method.
private fun getNotificationBuilder(): NotificationCompat.Builder {
// this intent opens the MainActivity when the user taps on the notification
val intentNotification = Intent(context, MainActivity::class.java)
val pendingIntentNotification = PendingIntent.getActivity(
context,
exampleNotificationID,
intentNotification,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val myBitmap = BitmapFactory.decodeResource(
context.resources,
R.drawable.puppy
)
val builder = NotificationCompat.Builder(context.applicationContext, exampleChannelID)
.setSmallIcon(R.drawable.chair)
.setContentIntent(pendingIntentNotification)
.setLargeIcon(myBitmap) // to show the image as a thumbnail when the notification is collapsed
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(myBitmap) // set the large image
.bigLargeIcon(null as Icon?) // to remove the thumbnail image when the notification is expanded
)
return builder
}
Output:

4. A large block of text:
Apply NotificationCompat.BigTextStyle to display a large block of text in the expanded content area.
private fun getNotificationBuilder(): NotificationCompat.Builder {
// this intent opens the MainActivity when the user taps on the notification
val intentNotification = Intent(context, MainActivity::class.java)
val pendingIntentNotification = PendingIntent.getActivity(
context,
exampleNotificationID,
intentNotification,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val myBitmap = BitmapFactory.decodeResource(
context.resources,
R.drawable.puppy
)
val builder = NotificationCompat.Builder(context.applicationContext, exampleChannelID)
.setSmallIcon(R.drawable.chair)
.setContentIntent(pendingIntentNotification)
.setLargeIcon(myBitmap)
.setStyle(
NotificationCompat.BigTextStyle()
.bigText("This is a large text\nin the expanded content area")
)
return builder
}
Output:

Related Articles:
References: