You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Firebase Notification:实现Gmail式可单独点击的合并通知

嘿,这个需求我之前帮不少开发者实现过,其实Android原生的通知系统就支持这种**分组通知(Grouped Notifications)**的功能,配合Firebase Cloud Messaging(FCM)就能完美复刻Gmail的样式。下面一步步给你拆解怎么做:

一、先搞懂核心逻辑:通知分组

Android从API 24(Android 7.0)开始支持通知分组——把同类型的通知归到一个组里,折叠状态下显示一条汇总通知,展开后能看到所有子通知,而且每个子通知都能单独点击跳转对应的内容,Gmail就是用的这个机制。

二、配置Firebase通知的分组标识

不管你是从FCM控制台发通知,还是服务器端推送,都要给同组的通知加上相同的分组Key,同时给每个子通知设置唯一标识(避免被覆盖)。

1. FCM控制台配置

在控制台的「高级选项」里:

  • 给所有要合并的通知设置相同的group字段(比如com.your.app.group.MAIL)
  • 每个通知设置不同的tag(比如邮件ID),确保子通知不会互相覆盖

2. 服务器端JSON示例

如果是自己的服务器推送,payload要包含分组和唯一标识:

{
  "to": "DEVICE_TOKEN",
  "notification": {
    "title": "新邮件:来自张三",
    "body": "项目进度更新..."
  },
  "data": {
    "mail_id": "12345",
    "group_key": "mail_group"
  },
  "android": {
    "notification": {
      "group": "mail_group",
      "tag": "mail_12345"
    }
  }
}
三、Android客户端实现分组逻辑

在你的FirebaseMessagingService子类里,处理通知的创建、分组和跳转逻辑:

1. 创建可单独点击的子通知

每个子通知要绑定唯一的跳转Intent,同时设置相同的分组Key,系统会自动把它们归为一组:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)
    
    // 解析通知数据
    val title = remoteMessage.notification?.title ?: "新通知"
    val body = remoteMessage.notification?.body ?: ""
    val mailId = remoteMessage.data["mail_id"] ?: ""
    val groupKey = remoteMessage.data["group_key"] ?: "default_group"
    
    // 子通知跳转Intent:点击打开对应邮件详情
    val detailIntent = Intent(this, MailDetailActivity::class.java).apply {
        putExtra("MAIL_ID", mailId)
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val detailPendingIntent = PendingIntent.getActivity(
        this,
        mailId.hashCode(), // 用唯一requestCode确保每个Intent不重复
        detailIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    
    // 构建子通知
    val childNotification = NotificationCompat.Builder(this, "MAIL_CHANNEL_ID")
        .setSmallIcon(R.drawable.ic_mail)
        .setContentTitle(title)
        .setContentText(body)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setContentIntent(detailPendingIntent)
        .setAutoCancel(true)
        .setGroup(groupKey) // 绑定分组Key
    
    // 发送子通知:用唯一ID(比如邮件ID哈希值)
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    notificationManager.notify(mailId.hashCode(), childNotification.build())
    
    // 同步创建汇总通知
    createGroupSummary(groupKey, notificationManager)
}

2. 创建折叠显示的汇总通知

汇总通知是折叠状态下显示的主通知,需要标记为groupSummary,同时绑定相同的分组Key:

private fun createGroupSummary(groupKey: String, notificationManager: NotificationManager) {
    // 汇总通知跳转Intent:点击打开邮件列表页
    val listIntent = Intent(this, MailListActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val listPendingIntent = PendingIntent.getActivity(
        this,
        0,
        listIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    
    // 构建汇总通知
    val summaryNotification = NotificationCompat.Builder(this, "MAIL_CHANNEL_ID")
        .setSmallIcon(R.drawable.ic_mail)
        .setContentTitle("新邮件")
        .setContentText("你有${getUnreadMailCount()}封未读邮件") // 可动态获取未读数量
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setContentIntent(listPendingIntent)
        .setAutoCancel(true)
        .setGroup(groupKey)
        .setGroupSummary(true) // 标记为汇总通知
    
    // 发送汇总通知:用固定ID(比如0)
    notificationManager.notify(0, summaryNotification.build())
}
四、关键注意事项
  • 通知渠道必须配置:Android 8.0及以上必须创建通知渠道,否则通知无法显示,记得在App启动时初始化:
private fun initNotificationChannels() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val mailChannel = NotificationChannel(
            "MAIL_CHANNEL_ID",
            "邮件通知",
            NotificationManager.IMPORTANCE_HIGH
        ).apply {
            description = "接收新邮件通知"
        }
        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(mailChannel)
    }
}
  • PendingIntent的requestCode必须唯一:每个子通知的requestCode不能重复,否则会导致所有子通知跳转同一个页面。
  • 优先用Data Message:如果发送FCM的「通知消息」,系统会自动显示通知,但你没法完全控制分组逻辑;建议用「数据消息」,这样能在onMessageReceived里完全自定义通知。
  • 旧设备兼容:API 23及以下不支持分组,这类设备会直接显示所有子通知,和Gmail的旧版本表现一致,属于正常情况。

这样就能实现和Gmail一模一样的多通知合并效果了,每个子通知都能单独点击跳转,折叠时显示汇总信息。如果还有细节问题可以再提~

内容的提问来源于stack exchange,提问作者Abdul Qayyum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:51:26