1. 简介
目标
在此 Codelab 中,您将学习如何对多平台应用进行插桩 (instrument),以便使用 FCM 主题将推送消息多播到应用实例的各个子群组。
完成后,您将能够利用 FCM 基础架构来管理这些子群组,以及通过子群组广播推送消息。
主题概览
主题是一种支持 FCM 基础架构的方式,可通过消息覆盖应用实例的子群组。
FCM 提供了用于发送消息以及维护对这些主题的订阅的 API。将应用实例与主题相关联和分离的操作分别称为订阅和退订
主题应该用于可公开访问的内容。例如,与天气动态相关的消息。如果您要发送敏感的用户消息,请使用 Firebase Admin SDK 通过多部设备广播消息。
基于主题的多播针对吞吐量进行了优化。
学习内容
- 如何让用户通过移动应用订阅(和退订)主题。
- 如何使用主题发送多播推送消息。
- 如何使用主题条件向主题组合发送消息。
- 如何在服务器端管理主题订阅以及如何批量订阅和取消订阅。
构建内容
- 订阅/取消订阅主题的 Android 应用,并在有消息发送到主题时接收消息。
- 使用 Firebase Admin SDK 的服务器端集成,将用于通过 FCM API 发送主题消息。
所需条件
- 您所选的浏览器,例如 Chrome。
- 用于开发 Java 应用的 IntelliJ IDEA IDE。
- 请务必在安装时选择启用 Gradle 支持。
- Android Studio IDE,用于开发 Android 应用。
- 运行 Android 应用的设备。以下任一操作:
- Android 模拟器(需要在 Android Studio 中进行设置)。
- 连接到计算机并设为开发者模式的 Android 实体设备。
- 用于创建和管理 Firebase 项目的 Google 账号。
2. 准备工作
获取代码
从命令行克隆 GitHub 代码库:
git clone https://github.com/firebase/quickstart-android.git fcm-codelab
示例代码将被克隆到 fcm-codelab
目录中。
cd fcm-codelab
此 Codelab 的起始应用位于 fcm-topics-codelab
分支的 messaging
目录中。请按照以下步骤找到起始代码。它包含 StockNewsApp
和 StockNewsServer
两个目录。前者包含起始 Android 应用,后者包含起始服务器端代码。
git checkout fcm-topics-codelab cd messaging/fcm-topics-codelab/starter
此 Codelab 的完成版本位于 messaging/fcm-topics-codelab/completed
目录下。
创建 Firebase 项目
- 在 Firebase 控制台中,点击添加项目,将 Firebase 项目命名为 StockNews,然后点击“继续”。注意:请记住您的 Firebase 项目的项目 ID(也可以点击修改图标设置自己偏好的项目 ID)。
- 您可以跳过启用 Google Analytics。在此 Codelab 中,您不需要该代码段。点击继续。
- 点击 Create project。
恭喜!您刚刚创建了 Firebase 项目。现在,您可以点击项目名称进入控制台。
3. 特定于平台的 Firebase 应用配置
启用 Firebase 支持所需的大多数代码更改已签入您正在使用的项目中。不过,为了增加对移动平台的支持,您需要:
- 在 Firebase 项目中注册所需的平台
- 下载特定于平台的配置文件,并将其添加到代码中。
在此 Codelab 中,我们将添加一个 Android Firebase 应用。
配置 Android
- 在 Firebase 控制台中,选择“设置”齿轮图标左侧导航栏顶部的项目设置,然后在常规页面中点击您的应用下的 Android 图标。
您应该会看到以下对话框:
- 要提供的重要值是 Android 软件包名称。将其设置为
com.ticker.stocknews
。- 此处提供的软件包名称必须与 StockNewsApp 起始代码的
AndroidManifest.xml
中提供的软件包名称相同。如果您想查找或更改它,请按照以下步骤操作:- 在 StockNewsApp 目录中,打开
app/src/main/AndroidManifest.xml
文件。 - 在
manifest
元素中,找到package
属性的字符串值。此值是 Android 软件包名称。
- 在 StockNewsApp 目录中,打开
- 此处提供的软件包名称必须与 StockNewsApp 起始代码的
- 在 Firebase 对话框中,将复制的软件包名称粘贴到 Android 软件包名称字段中。
- 此 Codelab 不需要使用调试签名证书 SHA-1,因为此应用不会发布。请将此项留空。
- 点击注册应用。
- 还是在 Firebase 控制台中,按照说明下载配置文件
google-services.json
。 - 您可以跳过其余设置步骤,因为起始应用代码中已配置所有其他设置。您会在 Firebase 控制台的主页面上看到您的应用。
- 将刚刚下载的
google-services.json
文件复制到messaging/fcm-topics-codelab/starter/StockNewsApp/app
目录。
4. 构建并运行您的应用
现在,您可以开始实际开发应用了!首先,构建并运行应用。
导入 starter 应用
启动 Android Studio,然后从起始代码目录导入 messaging/fcm-topics-codelab/starter/StockNewsApp
。
项目加载完成后,您可能还会看到一条提醒,指出 Git 将不会跟踪所有本地更改,您可以点击右上角的忽略或 X。(您所做的任何更改都不会保存到 Git 代码库中。)
如果您采用 Android 视图,那么在项目窗口的左上角应该会看到如下图所示的内容。(如果您处于 Project 视图,则需要展开项目才能看到相同的内容)
请注意,首次打开项目时,Android Studio 可能需要数秒时间在后台编译项目。在此期间,您会在 Android Studio 底部的状态栏中看到一个旋转图标:
建议您等待此过程完成后再更改代码。这样,Android Studio 就可以提取所有必要的组件。
此外,如果您看到“Reload for language changes to take effect?”的提示或类似内容,请选择“Yes”。
模拟器设置
如果您在设置 Android 模拟器时需要帮助,请参阅运行应用一文。
了解 Android 应用起始代码
- 起始代码是一个具有极简功能和界面的轻量级 Android 应用。
- firebase-messaging SDK 的依赖项已添加到
app/build.gradle
文件中。
- 在
AndroidManifest.xml
中,已添加MESSAGING_EVENT
回调处理程序。- 此处理程序
StockNewsMessagingService.java
会扩展FirebaseMessagingService
类,该类提供各种 Firebase Cloud Messaging 相关功能。如需了解详情,请参阅 FirebaseMessagingService 文档。
- 创建或刷新 FCM 注册令牌时,系统会调用
onNewToken
函数。如需了解详情,请参阅监控令牌生成。 - 收到消息且应用在前台运行时,系统会调用
onMessageReceived
函数。目前,它只记录收到的消息。- 如需详细了解后台和前台消息传送和处理之间的区别,请参阅在 Android 应用中接收消息。
- 此处理程序
- 此外,
AndroidManifest.xml
中还提供了一个名为StockNewsApplication
的 AndroidApplication
类。- 此类将是应用启动时实例化的第一个类。
- 在
StockNewsApplication
类的onCreate
函数中,添加了 FCM 注册令牌创建调用。它会生成一个有效的 FCM 注册令牌并将其记录在日志中。
MainActivity.java
会添加用于显示“商品类别”选项的RecyclerView
。SubscriptionAdapter.java
会实现RecyclerView.Adapter
,以绘制股票类别选择屏幕。- 每个股票类别旁边都有一个名称和订阅切换开关。
- 更改切换开关应会发出 FCM 主题订阅/退订调用。
- 您将在后面的部分中实现这些调用。
model/StockCategories.java
类包含所有库存类别及其关联主题名称的列表。
运行起始应用
- 将您的 Android 设备连接到计算机或启动模拟器。
- 在顶部的工具栏中,选择目标 Android 设备或模拟器,然后按运行按钮。
- 应用界面将如下所示:
- 该应用将创建一个 FCM 注册令牌并将其记录在日志中。不过,应用界面中不会有任何变化。
- 复制并保存 FCM 注册令牌,因为下一步会用到。
5. 发送测试消息
现在,您可以向上一步中设置的应用实例发送测试消息了。
导入起始服务器代码
启动 IntelliJ IDEA 并打开 messaging/fcm-topics-codelab/starter/StockNewsServer
项目。
左侧导航栏中的项目视图应如下所示:
请注意,IntelliJ IDEA 构建项目(包括拉取所需的依赖项)可能需要几分钟时间。
了解服务器起始代码
- 服务器起始代码是一个基于 Gradle 的 Java 项目。
build.gradle
文件中已添加对 firebase-admin SDK 的依赖项。此 SDK 提供对各种 FCM 消息发送功能的访问权限。
- 最后,还有两个类,即:
FcmSender.java
:此类包含以下值得注意的方法:initFirebaseSDK
:初始化 firebase-admin SDK。sendMessageToFcmRegistrationToken
:向 FCM 注册令牌发送消息。sendMessageToFcmTopic
:向 FCM 主题发送消息。sendMessageToFcmTopicCondition
:向 FCM 主题条件发送消息。
FcmSubscriptionManager.java
:此类包含允许从服务器端管理主题订阅的方法。initFirebaseSDK
:初始化 firebase-admin SDK。subscribeFcmRegistrationTokensToTopic
:为 FCM 主题订阅 FCM 注册令牌。unsubscribeFcmRegistrationTokensFromTopic
:从 FCM 主题中退订 FCM 注册令牌。
设置服务器代码
- 首先,我们需要设置一个 Firebase 服务账号,以允许 firebase-admin SDK 授权对 FCM API 的调用。
- 前往 Firebase 控制台,点击左侧导航栏中项目概览旁边的齿轮图标,然后选择项目设置。
- 在设置页面中,选择服务账号,然后点击创建服务账号。
- 现在,点击生成新的私钥按钮,系统就会开始自动下载您的密钥文件。
- 将密钥文件重命名为
service-account.json
,并将其复制到messaging/fcm-topics-codelab/starter/StockNewsServer/src/main/resources
文件夹中。 FcmSender.java
和FcmSubscriptionManager.java
都使用以下代码从类路径加载service-account.json
文件。
- 此时,服务器代码已准备就绪。从顶部菜单栏中依次选择“Run Build”->“Build Project”。
发送测试消息
- 在
FcmSender.java
中,找到sendMessageToFcmRegistrationToken
函数,然后将您从运行起始应用部分复制的 FCM 注册令牌插入registrationToken
字段。 - 在
main
函数中,仅取消注释sendMessageToFcmRegistrationToken
函数,然后点击“运行”以执行代码。- 观察 FCM 注册令牌是如何设置到
message
对象的Token
字段中的。 - 此外,请注意我们是如何使用
FirebaseMessaging
接口的send
API 的。
- 观察 FCM 注册令牌是如何设置到
- 这应向您在上一步中设置的应用实例发送消息。
- 当应用实例在前台运行时,您应该会看到记录的消息内容。
- 当应用实例在后台运行时,您会发现消息显示在通知栏中。
太棒了,您已使用 Firebase Admin SDK 向应用实例发送消息。详细了解如何在服务器中使用 Firebase Admin SDK。
6. 实现主题订阅 / 取消订阅
在此步骤中,您将在 Android 应用的“Stock Category”切换开关上实现主题订阅和退订操作。
当应用用户切换特定股票类别的开关时,系统会发出主题订阅或取消订阅调用。
查看代码
- 前往 Android 应用代码中的
SubscriptionAdapter.java
类,然后找到RecyclerViewViewHolder
类。
- 类构造函数使用
setOnCheckedChangeListener
为订阅切换开关设置监听器。 - 根据开关切换开关,可分别通过调用
subscribeToStockCategory
和unsubscribeFromStockCategory
方法来执行订阅和退订操作。 - RecyclerView 适配器的
onBindViewHolder
会调用setData
方法,以将 ViewHolder 绑定到适当的商品类别。
实现主题订阅
- 在
subscribeToStockCategory
方法中,您将实现对FirebaseMessaging
对象的subscribeToTopic
API 调用。代码可能如下所示:
void subscribeToStockCategory() { // Making call to FCM for subscribing to the topic for stockCategory FirebaseMessaging.getInstance().subscribeToTopic(stockCategory.getTopicName()).addOnSuccessListener( unused -> { // Subscribing action successful Log.i(TAG, "Subscribed to topic: " + stockCategory.getTopicName()); Toast.makeText(itemView.getContext(), "Subscribed to " + stockCategory.getCategoryName(), Toast.LENGTH_SHORT).show(); }); }
实现主题退订
- 同样,在 else 条件中,您将实现对
unsubscribeFromTopic
API 的调用。大致如下:
void unsubscribeFromStockCategory() { // Making call to FCM for unsubscribing from the topic for stockCategory FirebaseMessaging.getInstance().unsubscribeFromTopic(stockCategory.getTopicName()) .addOnSuccessListener(unused -> { // Unsubscribing action successful Log.i(TAG, "Unsubscribed from topic: " + stockCategory.getTopicName()); Toast.makeText(itemView.getContext(), "Unsubscribed from " + stockCategory.getCategoryName(), Toast.LENGTH_SHORT).show(); }); }
我们来试试看
- 运行应用并切换 Stock Category(股票)选项,以执行 Subscribe(订阅)和 Unsubscribe(取消订阅)操作。这如下所示:
订阅 | 退订 |
7. 发送您的第一条主题消息
在此步骤中,您将实现服务器端代码以发送 FCM 主题消息。
实现服务器端集成以发送主题消息
- 在服务器代码中,跳转到
FcmSender.java
并找到名为sendMessageToFcmTopic
的方法。
- 在第一行中,提供您要向其发送消息的 FCM 主题。
- 它是一个格式为
/topics/<Topic Name>
的字符串。例如/topics/Technology
。
- 它是一个格式为
- 在接下来的几行中,创建一个新的
message
对象(类似于sendMessageToFcmRegistrationToken
函数中定义的对象)。- 不同之处在于,您将设置
Topic
字段,而不是设置message
对象的Token
字段。
- 不同之处在于,您将设置
Message message = Message.builder() .putData("FOOTECH", "$1000") .setNotification( Notification.builder() .setTitle("Investor confidence in Tech Stocks growing") .setBody("Foo Tech leading the way in stock growth for Tech sector.") .build()) .setTopic(topicName) .build();
- 现在,添加对
FirebaseMessaging
实例的调用以发送消息(与sendMessageToFcmRegistrationToken
函数中进行的发送调用相同)。
FirebaseMessaging.getInstance().send(message);
- 最后,更新
main
函数,并仅允许调用sendMessageToFcmTopic
函数。
发送消息并验证接收
- 在发送主题消息之前,请首先确保您的应用程序实例订阅了要向其发送的主题。
- 只需切换相应的切换开关即可实现此目的。例如:
- 现在,您可以通过执行
FcmSender.java
的main
函数来发送主题消息。 - 和之前一样,您应该能够在应用实例上观察消息接收情况。
- 前台应用实例
- 应用实例位于后台
- 提示:请尝试退订您发送消息的主题,然后重新发送消息。您会发现消息未传送到应用实例。
8. 发送您的第一条主题条件消息
借助主题条件功能,您可以向多个主题组合发送消息,从而提供更具表现力的受众群体定义。
例如,在我们的 StockNews 应用中,考虑向订阅了“科技”或“汽车”主题的一组应用实例发送消息的可能性。例如,如果发生涉及 Waymo 的重要事件,就可能会出现这种情况。
借助主题,您可以使用以下运算符以布尔表达式的形式表示组合
- &&:逻辑 AND。例如,
'Technology' in topics && 'Automotive' in topics
- 仅定位到同时订阅了“技术”和“汽车”主题的应用实例。 - ||:逻辑 OR。例如,
'Technology' in topics || 'Automotive' in topics
- 定位订阅了“技术”或“汽车”主题的应用实例。 - () :用于分组的括号。例如,
'Technology' in topics && ('Automotive' in topics || 'Energy' in topics)
- 仅定位已订阅“技术”以及“汽车”或“能源”主题的应用实例。
详细了解如何构建发送请求以使用此功能。
实现服务器端集成以发送主题条件消息
- 返回服务器代码,跳转到
FcmSender.java
并找到名为sendMessageToFcmTopicCondition
的方法。
- 在第一行中,为
topicCondition
变量提供您要将消息发送到的主题条件。您可以将其设置为:'Technology' in topics && 'Automotive' in topics
。 - 在接下来的几行代码中,创建一个新的
message
对象(类似于sendMessageToFcmTopic
函数中定义的对象)。- 不同之处在于,您需要设置
Condition
字段,而不是设置对象的Topic
字段。
- 不同之处在于,您需要设置
Message message = Message.builder() .putData("FOOCAR", "$500") .setNotification( Notification.builder() .setTitle("Foo Car shows strong Q2 results") .setBody("Foo Car crosses 1B miles. Stocks rally.") .build()) .setCondition(topicCondition) .build();
- 现在,添加对
FirebaseMessaging
实例的调用以发送消息(与sendMessageToFcmTopic
函数中进行的发送调用相同)。
FirebaseMessaging.getInstance().send(message);
- 最后,更新
main
函数并启用仅调用sendMessageToFcmTopicCondition
函数的功能。
发送消息并验证收货
- 在发送主题消息之前,请首先为应用实例同时订阅“技术”和“汽车”主题,以确保应用实例满足指定的主题条件。
- 现在,您可以通过执行
FcmSender.java
的main
函数来发送主题消息。 - 与之前一样,您应该能够在应用实例上观察到消息接收情况。
- 前台应用实例
- 应用实例位于后台
- 奖励:您现在可以取消订阅“技术”主题,然后重新发送主题条件消息。您应该会发现应用实例未收到消息。
9. 要点回顾
我们来快速回顾一下到目前为止所学的知识。
- 如何从应用实例启动主题订阅/退订。
- 向主题发送消息并验证订阅的应用实例上的接收情况。
- 向主题条件发送消息,并在满足条件的应用实例上验证接收情况。
在下一部分中,您将学习如何为应用实例订阅 / 退订主题,而无需从客户端实例化调用。
10. 从服务器端管理主题订阅
到目前为止,在此 Codelab 中,所有主题订阅和取消订阅调用都是从应用实例发起的。
不过,在某些用例中,您可能需要从服务器端管理主题订阅。例如,您可能希望为现有用户群体的某个子群组订阅新主题,而无需等待应用发布。
在本部分中,您将学习如何使用 Firebase Admin SDK 通过从服务器端进行调用,为主题订阅和退订一批 FCM 注册令牌。
实现 FCM 注册令牌对 FCM 主题的服务器端订阅
- 在服务器代码中,跳转到
FcmSubscriptionManager.java
类。找到名为subscribeFcmRegistrationTokensToTopic
的方法。您将在此处实现对subscribeToTopic
API 的调用。
- 让我们为应用实例订阅 Energy 主题。为此,请先为以下两个字段提供数据:
registrationTokens
:以英文逗号分隔的字符串列表,表示要为其创建主题订阅的 FCM 注册令牌。topicName
:能源主题的主题名称,即/topics/Energy
。
- 在接下来的几行代码中,按照以下方式实现调用:
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic( registrationTokens, topicName);
- 您可以检查
TopicManagementResponse
来获取一些概要结果统计信息。例如,使用getSuccessCount
输出成功创建的主题订阅的数量。
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
- 最后,在
main
函数中,仅启用对subscribeFcmRegistrationTokensToTopic
函数的调用。
创建订阅并发送主题消息
- 此时,您可以创建主题订阅并向其发送消息。
- 执行
FcmSubscriptionManager.java
类的main
函数。这将创建一个主题订阅。 - 现在,设置发送消息所需的代码。与之前类似,
- 在
FcmSender.java
中,找到sendMessageToFcmTopic
函数。 - 将
topicName
设为能源主题,即/topics/Energy
。 - 创建一个
Message
对象,并使用setTopic
将其定位到相应主题。 - 最后,更新
main
方法以仅启用sendMessageToFcmTopic
函数。
- 在
- 执行
FcmSender.java
的main
函数。这会将消息发送到您的应用实例,您可以在应用中按如下方式观察该消息。- 前台应用实例
- 后台应用实例
在服务器端取消 FCM 注册令牌对 FCM 主题的订阅
- 如需取消订阅服务器端主题,请使用此
unsubscribeFromTopic
API。您将向FcmSubscriptionManager.java
类的unsubscribeFcmRegistrationTokensFromTopic
函数添加相关代码。
- 实现服务器端取消订阅代码并通过发送主题消息验证其效果,这将留作练习题供您完成。
11. 恭喜
恭喜,您已成功使用 FCM 主题向应用实例的子群组发送多播消息。这样,您就可以更轻松地通过相关内容及时触达用户。
后续步骤
现在,您已完成此 Codelab,不妨考虑使用以下指南尝试其他平台的主题: