androidengineers.Book a session

Android Platform Services

Notification Channels & Custom Styles

article25 minMedium

Android's notification system is rich and customizable. Understanding notification channels, styles, and actions lets you build engaging, well-behaved notifications that users actually want.

Notification Channels: Mandatory on API 26+

Channels let users control notification types independently. Always create all channels in Application.onCreate():

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        createNotificationChannels()
    }

    private fun createNotificationChannels() {
        val manager = getSystemService(NotificationManager::class.java)

        val channels = listOf(
            NotificationChannel("messages", "Messages", NotificationManager.IMPORTANCE_HIGH).apply {
                description = "Direct messages from other users"
                enableVibration(true)
                enableLights(true)
                lightColor = Color.BLUE
                setShowBadge(true)
            },
            NotificationChannel("social", "Social", NotificationManager.IMPORTANCE_DEFAULT).apply {
                description = "Likes, comments, and follows"
                setShowBadge(true)
            },
            NotificationChannel("promotions", "Promotions", NotificationManager.IMPORTANCE_LOW).apply {
                description = "Deals and promotional offers"
                setShowBadge(false)
            },
            NotificationChannel("reminders", "Reminders", NotificationManager.IMPORTANCE_HIGH).apply {
                description = "Event and appointment reminders"
                enableVibration(true)
            }
        )

        // Create group (optional: groups multiple channels in settings)
        val socialGroup = NotificationChannelGroup("social_group", "Social")
        manager.createNotificationChannelGroup(socialGroup)

        channels.forEach { channel ->
            if (channel.id in listOf("social", "messages")) {
                channel.group = "social_group"
            }
            manager.createNotificationChannel(channel)
        }
    }
}

BigTextStyle

NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_message)
    .setContentTitle("Alice")
    .setContentText("Hey, are you free this weekend?")  // short preview
    .setStyle(
        NotificationCompat.BigTextStyle()
            .bigText("Hey, are you free this weekend? We're planning a hike up to the summit and it'd be great if you could join us! Let me know by Thursday.")
            .setBigContentTitle("Alice")
            .setSummaryText("Direct message")
    )
    .build()

InboxStyle (Stacked Messages)

NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_messages)
    .setContentTitle("3 new messages")
    .setStyle(
        NotificationCompat.InboxStyle()
            .addLine("Alice: Are you free this weekend?")
            .addLine("Bob: Great work on the presentation!")
            .addLine("Carol: Call me when you get a chance")
            .setBigContentTitle("3 new messages")
            .setSummaryText("inbox")
    )
    .build()

BigPictureStyle

val bitmap = Glide.with(context).asBitmap().load(imageUrl).submit().get()

NotificationCompat.Builder(context, "social")
    .setSmallIcon(R.drawable.ic_photo)
    .setContentTitle("Alice liked your photo")
    .setStyle(
        NotificationCompat.BigPictureStyle()
            .bigPicture(bitmap)
            .bigLargeIcon(null as Bitmap?)  // hide large icon when expanded
    )
    .setLargeIcon(userAvatarBitmap)
    .build()

MessagingStyle (Chat Notifications)

val person = Person.Builder()
    .setName("Alice")
    .setIcon(IconCompat.createWithBitmap(aliceAvatarBitmap))
    .build()

val messagingStyle = NotificationCompat.MessagingStyle(me)
    .setConversationTitle("Work Group")  // null for 1:1 conversations
    .addMessage("Hey, meeting at 3pm?", timestamp1, alice)
    .addMessage("Sure, conference room B?", timestamp2, bob)
    .addMessage("Works for me!", timestamp3, me)

NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_chat)
    .setStyle(messagingStyle)
    .setShortcutId("conversation_${conversationId}")  // links to app shortcut
    .addAction(buildReplyAction(conversationId))       // inline reply
    .build()

Inline Reply Action

fun buildReplyAction(conversationId: String): NotificationCompat.Action {
    val remoteInput = RemoteInput.Builder("reply_key")
        .setLabel("Reply…")
        .build()

    val replyPendingIntent = PendingIntent.getBroadcast(
        context,
        conversationId.hashCode(),
        Intent(context, ReplyReceiver::class.java).putExtra("conversation_id", conversationId),
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
    )

    return NotificationCompat.Action.Builder(
        R.drawable.ic_reply, "Reply", replyPendingIntent
    ).addRemoteInput(remoteInput).build()
}

class ReplyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val reply = RemoteInput.getResultsFromIntent(intent)?.getCharSequence("reply_key") ?: return
        val conversationId = intent.getStringExtra("conversation_id") ?: return

        // Send reply (use WorkManager for the actual network call)
        WorkManager.getInstance(context).enqueue(
            OneTimeWorkRequestBuilder<SendReplyWorker>()
                .setInputData(workDataOf("conversation_id" to conversationId, "reply" to reply.toString()))
                .build()
        )
    }
}

Key Takeaways

StyleBest for
BigTextStyleLong text messages; email previews
InboxStyleMultiple items (emails, updates) stacked
BigPictureStyleImage previews (photo likes, post previews)
MessagingStyleChat conversations; shows avatar and sender name
Inline replyChat apps; lets users respond without opening the app
Channel groupsOrganize related channels in settings UI

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Notification Channels & Custom Styles | Android System Design | Android Engineers