首页 / Android 入门教程 / 通知进阶

Android 入门教程

通知进阶

本教程共 100 篇 · 第 85 篇 · 更新于 2026-07-28 · 约 8 分钟阅读

AndroidAndroid 入门教程通知NotificationMessagingStyleRemoteInput

85. 通知进阶

本节目标:掌握展开式通知样式、分组通知、进度通知、直接回复、全屏 Intent 等进阶用法,能根据场景选择合适的通知样式。

上一章的基本通知只能显示一行文字。实际场景里通知要承载更多内容:长文本、图片、多条消息、操作按钮。这章讲进阶。

展开式通知

通知默认收起成一行。下拉能展开成更大区域,用 setStyle 配样式模板。

BigTextStyle:长文本

val bigTextStyle = NotificationCompat.BigTextStyle()
    .bigText("这是一段很长的文本,超过一行会被截断。展开后能完整显示。继续写..." +
            "还能换行显示,最多支持 1000+ 字符。")

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("文章更新")
    .setStyle(bigTextStyle)

收起时显示 contentText 的前一行,展开后显示完整 bigText

BigPictureStyle:大图

val bitmap = BitmapFactory.decodeResource(resources, R.drawable.big_image)

val bigPictureStyle = NotificationCompat.BigPictureStyle()
    .bigPicture(bitmap)
    .bigLargeIcon(null)  // 展开时隐藏右下小图标

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("图片分享")
    .setLargeIcon(bitmap)
    .setStyle(bigPictureStyle)

适合「收到一张图片」「分享了一张图片」这种场景。

InboxStyle:多行汇总

val inboxStyle = NotificationCompat.InboxStyle()
    .addLine("张三:在吗?")
    .addLine("李四:会议改到 3 点")
    .addLine("王五:文件已发")
    .setSummaryText("3 条未读")

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setContentTitle("3 条新消息")
    .setStyle(inboxStyle)

适合汇总多条内容,比如邮件客户端显示未读邮件列表。

MessagingStyle:聊天会话

专门给即时通讯应用用,显示对话气泡:

val messagingStyle = NotificationCompat.MessagingStyle("我")
    .addMessage("在吗?", System.currentTimeMillis() - 60000, "张三")
    .addMessage("在的", System.currentTimeMillis() - 30000, null)  // null 表示自己发的
    .addMessage("什么时候到?", System.currentTimeMillis(), "张三")

val builder = NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.ic_notification)
    .setStyle(messagingStyle)

Android 9+ 推荐用 Person 类表示发送者,能显示头像:

val person = Person.Builder()
    .setName("张三")
    .setImportant(true)
    .build()

messagingStyle.addMessage("在吗?", System.currentTimeMillis(), person)
Tip

聊天应用必须用 MessagingStyle,否则在 Android Auto、Wear OS 等设备上体验差。

MediaStyle:媒体播放

媒体播放通知,带播放/暂停按钮:

val mediaStyle = androidx.media.app.NotificationCompat.MediaStyle()
    .setShowActionsInCompactView(0, 1, 2)  // 紧凑视图显示哪些按钮

val builder = NotificationCompat.Builder(context, "music")
    .setSmallIcon(R.drawable.ic_music)
    .setContentTitle("正在播放")
    .setContentText("歌曲名")
    .addAction(R.drawable.ic_prev, "上一首", prevPendingIntent)
    .addAction(R.drawable.ic_pause, "暂停", pausePendingIntent)
    .addAction(R.drawable.ic_next, "下一首", nextPendingIntent)
    .setStyle(mediaStyle)

Android 13+ 媒体通知要配合 MediaSession 使用。

分组通知

多个通知能归到一组,折叠显示:

// 每条消息单独通知
val builder1 = NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("张三")
    .setContentText("在吗?")
    .setGroup("chat_group")

val builder2 = NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("李四")
    .setContentText("会议改时间")
    .setGroup("chat_group")

// 汇总通知
val summary = NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("2 条新消息")
    .setStyle(NotificationCompat.InboxStyle()
        .addLine("张三:在吗?")
        .addLine("李四:会议改时间"))
    .setGroup("chat_group")
    .setGroupSummary(true)

NotificationManagerCompat.from(context).apply {
    notify(1, builder1.build())
    notify(2, builder2.build())
    notify(0, summary.build())  // 汇总最后发
}

要点:

  • setGroup("chat_group") 标记同组。
  • setGroupSummary(true) 是汇总通知。
  • 汇总通知要最后发,系统才会折叠。
  • 收起时只显示汇总,展开显示各条。

进度通知

下载/上传时显示进度条:

不确定进度

val builder = NotificationCompat.Builder(context, "download")
    .setSmallIcon(R.drawable.ic_download)
    .setContentTitle("下载中")
    .setContentText("下载进行中")
    .setProgress(0, 0, true)  // 不确定模式
    .setOngoing(true)  // 不能滑动删除

notify(NOTIFICATION_ID, builder.build())

setProgress(0, 0, true) 显示转圈,不知道具体进度。

确定进度

// 更新进度
fun updateProgress(current: Int, total: Int) {
    val builder = NotificationCompat.Builder(context, "download")
        .setSmallIcon(R.drawable.ic_download)
        .setContentTitle("下载中")
        .setContentText("$current / $total KB")
        .setProgress(total, current, false)  // 确定模式

    NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build())
}

// 完成
fun complete() {
    val builder = NotificationCompat.Builder(context, "download")
        .setSmallIcon(R.drawable.ic_download)
        .setContentTitle("下载完成")
        .setContentText("点击打开")
        .setProgress(0, 0, false)  // 移除进度条

    NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build())
}
Note

进度更新频率别太高,每秒 1-2 次就够,太频繁系统会合并显示。

直接回复

让用户在通知里直接输入文字回复,不用打开应用。

// 1. 创建 RemoteInput
val remoteInput = RemoteInput.Builder("KEY_TEXT_REPLY")
    .setLabel("回复")
    .build()

// 2. 创建回复 Intent
val replyIntent = Intent(context, ReplyReceiver::class.java).apply {
    action = "ACTION_REPLY"
    putExtra("message_id", 123)
}
val replyPendingIntent = PendingIntent.getBroadcast(
    context, 123, replyIntent,
    PendingIntent.FLAG_MUTABLE  // 直接回复必须 MUTABLE
)

// 3. 创建 Action
val action = NotificationCompat.Action.Builder(
    R.drawable.ic_reply,
    "回复",
    replyPendingIntent
)
    .addRemoteInput(remoteInput)
    .build()

// 4. 加到通知
val builder = NotificationCompat.Builder(context, "messages")
    .setSmallIcon(R.drawable.ic_notification)
    .setContentTitle("张三")
    .setContentText("在吗?")
    .addAction(action)

接收回复:

class ReplyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == "ACTION_REPLY") {
            val replyText = RemoteInput.getResultsFromIntent(intent)
                ?.getCharSequence("KEY_TEXT_REPLY")
            val messageId = intent.getIntExtra("message_id", -1)

            // 处理回复...

            // 更新通知,确认收到回复
            val repliedNotification = NotificationCompat.Builder(context, "messages")
                .setSmallIcon(R.drawable.ic_notification)
                .setContentText("回复已发送:$replyText")
                .build()

            NotificationManagerCompat.from(context).notify(messageId, repliedNotification)
        }
    }
}
Warning

直接回复的 PendingIntent 必须 FLAG_MUTABLE,因为系统要往里塞用户输入的文本。

全屏 Intent

紧急通知(来电、闹钟)能直接全屏覆盖:

val fullScreenIntent = Intent(context, CallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(
    context, 0, fullScreenIntent, PendingIntent.FLAG_IMMUTABLE
)

val builder = NotificationCompat.Builder(context, "calls")
    .setSmallIcon(R.drawable.ic_call)
    .setContentTitle("来电")
    .setContentText("张三")
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setCategory(NotificationCompat.CATEGORY_CALL)
    .setFullScreenIntent(fullScreenPendingIntent, true)

行为:

  • 锁屏时:直接弹出全屏 Activity。
  • 解锁时:以高优先级通知显示。
Warning

Android 14+ 全屏 Intent 要申请 USE_FULL_SCREEN_INTENT 权限,且只允许通话和闹钟类应用使用。

通知元数据

设通知的元数据,让系统更好分类:

builder.setCategory(NotificationCompat.CATEGORY_MESSAGE)  // 消息类
       .addPerson(uri)  // 关联联系人
       .setVisibility(NotificationCompat.VISIBILITY_PRIVATE)  // 锁屏隐私

CATEGORY_*MESSAGECALLALARMEMAILEVENTRECOMMENDATION 等。系统根据类别在勿扰模式下区别处理。

定时通知

通知能延迟发送:

builder.setTimeoutAfter(60_000)  // 60 秒后自动消失

或者用 AlarmManager 在指定时间发:

val alarmManager = getSystemService(AlarmManager::class.java)
val triggerAtMillis = System.currentTimeMillis() + 60 * 60 * 1000  // 1 小时后

alarmManager.setExactAndAllowWhileIdle(
    AlarmManager.RTC_WAKEUP,
    triggerAtMillis,
    pendingIntent  // 触发的 BroadcastReceiver
)

Receiver 里再发通知。Android 12+ 精确闹钟要申请 SCHEDULE_EXACT_ALARM 权限。

通知快捷设置

通知里加「快捷设置」开关(Android 12+):

builder.addAction(
    NotificationCompat.Action.Builder(
        R.drawable.ic_settings,
        "设置",
        settingsPendingIntent
    ).build()
)

或者用 Bubble(气泡)展示浮动窗口,适合聊天应用。

常见坑

  1. 展开式通知用错样式:聊天用 MessagingStyle,长文本用 BigTextStyle。
  2. 分组通知忘了发汇总:每条都单独展开,不折叠。
  3. 进度更新太频繁:系统合并,看起来卡顿。降到每秒 1-2 次。
  4. 直接回复 PendingIntent 用 IMMUTABLE:崩,必须 MUTABLE。
  5. 全屏 Intent 滥用:非通话/闹钟应用用,被 Play 拒审。
  6. Bubble 没配 Activity:Bubble 要 Activity 支持 allowEmbedded,否则不显示。

小结

通知进阶按场景选样式:长文本用 BigTextStyle,图片用 BigPictureStyle,聊天用 MessagingStyle,多行汇总用 InboxStyle。分组通知用 setGroup + setGroupSummary。进度通知用 setProgress,直接回复用 RemoteInput + FLAG_MUTABLE。紧急通知用 setFullScreenIntent,但要申请权限。

下一章讲系统服务概览,看 Android 还提供哪些系统能力。