推送通知中的 Topic Subscription — 含义、工作原理与配置方法

作者: IT Sectr 发布日期: 2026-03-21 阅读时间: 8 分钟

Topic Subscription — 是一种 Firebase Cloud Messaging 机制,可以根据兴趣对设备进行分组,并向整个订阅者类别发送通知。无需向数千个单独的 Registration Token 发送消息,只需向一个主题发送一条消息即可。根据 Firebase, 2025 的数据,Topic Subscription 被用于新闻应用、体育直播和营销活动中的大规模通知投递。

要点

  • Topic Subscription — 设备订阅 FCM 主题频道以接收群组通知。
  • 一台设备可以订阅无限数量的主题
  • 订阅可以通过客户端和服务器通过 FCM HTTP API 进行管理。
  • 主题在首次订阅时自动创建 — 无需预先配置。
  • 向主题发送消息时,只需指定主题名称而非令牌列表。

FCM 中的 Topic Subscription 是什么

Topic Subscription — 是一种群组推送通知机制,设备通过订阅已命名的频道(主题)并接收发送到这些频道的消息。每个主题由一个字符串名称标识,例如 news_sports 或 weather_alerts。

主题的工作原理

当设备订阅一个主题时,FCM 会将其 Registration Token 添加到该主题的接收者列表中。当向主题发送消息时,FCM 会自动将副本路由到每个订阅的设备。Firebase 不限制每台设备的订阅数量 — 应用可以同时将用户订阅到数十个主题。

主题与单独发送对比

主题的主要优势是可扩展性。要向一百万用户发送通知,只需向 FCM 发送一个带有主题名称的 HTTP 请求。而单独发送则需要一百万个请求或批量发送(每次最多 500 个令牌)。主题还简化了服务器端的逻辑 — 无需为每个类别存储令牌列表。

参数单独发送Topic Subscription
请求数量每个令牌一个或批量最多 500每个主题一个
订阅管理在服务器上(令牌列表)在客户端或服务器上
动态分组需要更新列表通过订阅自动完成
接收者限制一个请求中最多 500无限制

主题使用示例

Topic Subscription 广泛用于新闻应用中的内容分类 — 订阅"体育"、"政治"、"科技"等主题可以投递相关的通知。在电子商务中,主题用于特定产品类别的折扣通知。在即时通讯和社交网络中,主题用于群组事件通知。

FCM 限制和限额

Firebase 对主题使用施加了限制。一个应用最多可以有 2000 个主题。每台设备最多可以订阅 2000 个主题。订阅/取消订阅的频率也有限制 — 每个项目每分钟不超过 3000 次操作。超出限制将导致临时封锁。对于主题数量众多的项目,建议使用条件(condition)而不是主题 — FCM 支持逻辑表达式进行定向。

主题订阅的工作原理

Topic Subscription 过程包括三个阶段:在客户端初始化订阅、在 FCM 基础设施中注册以及确认操作。成功订阅后,设备开始接收发送到该主题的消息。

订阅的生命周期

当客户端调用 subscribeToTopic() 方法时,Firebase SDK 向 FCM 服务器发送请求。服务器检查操作的允许性,并将设备令牌添加到主题的订阅者列表中。FCM 向客户端返回成功订阅的确认。从此刻起,所有发送到该主题的消息都将投递到设备。

主题的自动创建

无需在 Firebase 控制台中预先创建主题。当任何设备首次订阅名为 news_promo 的主题时,FCM 会自动创建该主题。如果最后一个设备取消订阅,主题仍保留在系统中但处于非活动状态,并在有新订阅时恢复工作。

Android 上的主题订阅

Android 上,订阅和取消订阅主题通过 FirebaseMessaging SDK 完成。subscribeToTopic() 和 unsubscribeFromTopic() 方法接受主题名称作为参数。操作是异步的,需要处理结果。

基本主题订阅

要订阅,只需使用目标主题的名称调用 subscribeToTopic() 即可。Firebase SDK 独立管理网络请求和失败时的重试。建议在成功获取 Registration Token 后订阅主题。

kotlin
class TopicSubscriber(private val context: Context) {

    fun subscribeToNewsTopic() {
        FirebaseMessaging.getInstance()
            .subscribeToTopic("news_latest")
            .addOnCompleteListener { task ->
                val msg = if (task.isSuccessful) {
                    "Subscribed to news topic"
                } else {
                    "Subscription failed"
                }
                Log.d("FCM", msg)
            }
    }

    fun unsubscribeFromNewsTopic() {
        FirebaseMessaging.getInstance()
            .unsubscribeFromTopic("news_latest")
            .addOnCompleteListener { task ->
                Log.d("FCM", "已取消订阅:${task.isSuccessful}")
            }
    }
}

管理多个订阅

在实际应用中,用户可以订阅多个类别。为了方便管理,创建一个管理类来同步订阅状态与服务器端。当用户登录时,从个人资料中恢复其订阅。

kotlin
class SubscriptionManager(private val context: Context) {

    private val fcm = FirebaseMessaging.getInstance()

    suspend fun syncSubscriptions(topics: List<String>) {
        topics.forEach { topic ->
            fcm.subscribeToTopic(topic).await()
        }
    }

    suspend fun removeAllSubscriptions() {
        val savedTopics = getSavedTopics()
        savedTopics.forEach { topic ->
            fcm.unsubscribeFromTopic(topic).await()
        }
    }

    private fun getSavedTopics(): List<String> {
        return listOf("news_latest", "promotions", "updates")
    }
}

iOS 上的主题订阅

iOS 上,订阅主题的过程在逻辑上与 Android 相同,但使用 Firebase Messaging 的 Swift API。subscribe 和 unsubscribe 方法在 Messaging 实例上调用,也是异步的。

iOS 上的订阅实现

要在 iOS 应用中订阅主题,使用 Messaging.subscribe() 方法。重要的是在初始化 Firebase 并获取 Registration Token 后调用订阅。Apple 建议在订阅主题之前请求通知权限。

swift
import FirebaseMessaging

class PushTopicManager {

    func subscribeToTopic(topic: String) {
        Messaging.messaging().subscribe(toTopic: topic) { error in
            if let error = error {
                Log.e("FCM", "订阅错误:\(error)")
            } else {
                Log.d("FCM", "已订阅 \(topic)")
            }
        }
    }

    func unsubscribeFromTopic(topic: String) {
        Messaging.messaging().unsubscribe(fromTopic: topic) { error in
            if let error = error {
                Log.e("FCM", "取消订阅错误:\(error)")
            }
        }
    }
}

iOS 订阅的特点

在 iOS 上,主题订阅也与 Firebase 从 APNs 获取的 Registration Token 绑定。如果 APNs 令牌发生变化(例如在设备恢复后),Firebase 会自动将订阅转移到新令牌。然而,在极少数情况下,可能需要在更新 Registration Token 后重新订阅。

从服务器管理订阅

服务器端管理订阅允许在无需客户端应用参与的情况下订阅和取消订阅设备。这对于管理、A/B 测试和后端的订阅管理非常有用。

用于订阅管理的 FCM HTTP API

Firebase 提供 REST API 用于批量管理订阅。/v1/projects/{project_id}/subscriptions 方法允许在一个请求中订阅多达 1000 台设备。API 使用设备的 Registration Token 进行标识。

js
const admin = require("firebase-admin")

async function subscribeUsersToTopic(tokens, topic) {
    try {
        const response = await admin
            .messaging()
            .subscribeToTopic(tokens, topic)
        Log.info(`Success: ${response.successCount}`)
        Log.info(`Failures: ${response.failureCount}`)
    } catch (error) {
        Log.error("订阅错误", error)
    }
}

服务器端管理的使用场景

服务器端订阅管理用于多种场景。在用户注册时,服务器自动将其订阅到基础主题。当在 Web 版本中更改偏好时,服务器同步移动设备上的订阅。管理员可以订阅测试设备到内部主题以进行调试。对于批量操作,FCM 提供 Instance Group 方法,允许通过一个组标识符管理一组设备的订阅。

订阅状态监控

Firebase 不提供内置 API 来检查设备的当前订阅。建议开发者在服务器端维护自己的订阅数据库。每次应用启动时,客户端通过发送活动主题列表与服务端同步其订阅。这可以检测不同步并在需要时恢复订阅。对于审计,使用 Firebase Cloud Functions 日志 — 每个 subscribe/unsubscribe 操作都可以被记录。

常见问题

一个 Firebase 项目可以创建多少个主题?

最大主题数量为每个应用 2000 个。如果需要更多,请考虑使用设备组 (Device Groups) 或按令牌单独发送。

如何查看设备订阅了哪些主题?

Firebase 不提供直接获取设备订阅列表的 API。建议开发者在自己的服务器上存储订阅状态并与客户端同步。

取消订阅不存在的主题会怎样?

FCM 返回成功结果。Firebase 将取消订阅不存在的主题视为无操作 — 不会生成错误,状态不会改变。

可以从 Firebase 控制台向主题发送通知吗?

可以,在 Firebase 控制台的 Cloud Messaging 部分,您可以选择主题作为目标受众,并通过 Web 界面发送测试或生产通知。

主题订阅需要多长时间才能生效?

通常订阅会在几秒钟内激活。然而,在极少数情况下,由于信息在 FCM 服务器间传播,延迟可能达到 30–60 秒

总结

  • Topic Subscription — 通过 Firebase Cloud Messaging 实现的群组推送通知机制。
  • 订阅通过客户端的 subscribeToTopic() (Android) 或 subscribe() (iOS) 方法完成。
  • 一台设备可以同时订阅最多 2000 个主题
  • 服务器 API 允许在一个请求中管理最多 1000 台设备的订阅。
  • 主题在首次订阅时自动创建,无需预先配置。
  • 在处理大量受众时,Topic Subscription 比单独发送更优。
  • 对于关键通知,将主题与单独发送相结合以确保投递。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读