1. 简介
目标
在此 Codelab 中,您将学习如何对多平台应用进行插桩 (instrument),以便使用 FCM 主题向应用实例的各个子组多播推送消息。
完成后,您可以利用 FCM 基础架构管理这些子群组,并通过子群组进行多播推送消息。
主题概览
主题是一种支持 FCM 基础架构的方式,可通过消息覆盖应用实例的子群组。
FCM 提供用于发送消息以及维护对这些主题的订阅的 API。将应用实例与主题相关联和取消关联的行为分别称为订阅和退订
主题应该用于可公开访问的内容。例如,关于天气动态的消息。如果要发送用户敏感消息,请使用 Firebase Admin SDK 通过多台设备多播消息。
基于主题的多播针对吞吐量进行了优化。
学习内容
- 如何通过移动应用为用户订阅(和退订)主题。
- 如何使用主题发送多播推送消息。
- 如何使用主题条件向主题组合发送消息。
- 如何在服务器端管理主题订阅以及如何进行批量订阅和取消订阅。
构建内容
- 可以订阅/退订主题并在收到主题的消息时接收消息的 Android 应用。
- 使用 Firebase Admin SDK 的服务器端集成,用于通过 FCM API 发送主题消息。
所需条件
- 您选择的浏览器,例如 Chrome。
- 用于开发 Java 应用的 IntelliJ IDEA IDE。
- 请确保在安装时选择支持 Gradle。
- 用于开发 Android 应用的 Android Studio IDE。
- 一台运行 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 并未跟踪所有本地更改,您可以点击右上角的“Ignore”或“X”。(您不会将任何更改推送回 Git 代码库。)
如果您处于 Android 视图,那么在项目窗口的左上角应该会看到如下图所示的内容。(如果您处于 Project 视图,则需要展开项目才能看到同一内容)
请注意,首次打开项目时,Android Studio 可能需要数秒时间在后台编译项目。在此期间,您会在 Android Studio 底部的状态栏中看到一个旋转图标:
我们建议您等到此过程完成后再更改代码。这样,Android Studio 就可以拉取所有必要的组件。
此外,如果您看到“重新加载使语言更改生效吗?”的提示或类似提示,请选择“是”。
模拟器设置
如果您在设置 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 消息发送功能。
- 最后,有两种类,即 viz:
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 控制台,点击左侧导航栏中项目概览旁边的齿轮图标,然后选择项目设置。
- 在设置页面中,选择服务账号,然后点击创建服务账号。
- 现在,点击 Generate new private key 按钮,系统会自动下载您的密钥文件。
- 将密钥文件重命名为
service-account.json
,并将其复制到messaging/fcm-topics-codelab/starter/StockNewsServer/src/main/resources
文件夹中。 FcmSender.java
和FcmSubscriptionManager.java
都使用以下代码从类路径加载service-account.json
文件。
- 此时,服务器代码已准备就绪。从顶部菜单栏中运行 Build -> Build Project。
发送测试消息
- 在
FcmSender.java
中,找到sendMessageToFcmRegistrationToken
函数,然后将您从运行起始应用部分复制的 FCM 注册令牌插入registrationToken
字段。 - 在
main
函数中,仅取消注释sendMessageToFcmRegistrationToken
函数,然后点击“运行”以执行代码。- 观察在
message
对象的Token
字段中设置 FCM 注册令牌的情况。 - 此外,请注意我们如何使用
FirebaseMessaging
接口的send
API。
- 观察在
- 这应该会向您在上一步中设置的应用实例发送一条消息。
- 当应用实例处于前台时,您应该会看到消息内容被记录。
- 当该应用实例在后台运行时,您会看到消息显示在通知栏中。
太棒了,您使用 Firebase Admin SDK 向应用实例发送消息。详细了解如何在服务器中使用 Firebase Admin SDK。
6. 实现主题订阅 / 取消订阅
在此步骤中,您将在 Android 应用的“股票类别”切换开关上实现主题订阅和退订操作。
当应用用户切换特定股票类别的开关时,将发出主题订阅或取消订阅调用。
查看代码
- 转到 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
函数中定义的对象)。- 不同之处在于,您不是设置
message
对象的Token
字段,而是设置Topic
字段。
- 不同之处在于,您不是设置
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
函数中进行的 send 调用相同)。
FirebaseMessaging.getInstance().send(message);
- 最后,更新
main
函数并仅允许调用sendMessageToFcmTopic
函数。
发送消息并验证收到
- 发送主题消息之前,请先确保您的应用实例已订阅您要发送到的主题。
- 翻转相应的切换开关即可完成此操作。例如:
- 现在,您可以通过执行
FcmSender.java
的main
函数来发送主题消息。 - 和之前一样,您应该能够观察应用实例上的消息接收情况。
- 前台应用实例
- 后台应用实例
- 额外好处:请尝试退订您收到的主题,然后重新发送邮件。您会看到消息未传送到应用实例。
8. 发送您的第一条主题条件消息
通过主题条件功能,您可以向主题组合发送消息,以便提供更具表现力的受众群体定义。
例如,在我们的 StockNews 应用中,考虑是否能够向一组订阅了技术或汽车主题的应用实例发送消息。例如,当发生涉及 Waymo 的值得注意的事件时,就会出现这种情况。
Topics 允许您使用以下运算符,以布尔表达式的形式来表达您的组合
- &&:逻辑与。例如,
'Technology' in topics && 'Automotive' in topics
- 仅定位同时订阅了技术和汽车主题的应用实例。 - ||:逻辑 OR。例如,
'Technology' in topics || 'Automotive' in topics
- 定位订阅了技术或汽车主题的应用实例。 - ():用于分组的圆括号。例如,
'Technology' in topics && ('Automotive' in topics || 'Energy' in topics)
- 仅定位已订阅“Tech”以及“Auto”或“Energy”主题的应用实例。
详细了解如何构建发送请求以使用此功能。
实现用于发送主题条件消息的服务器端集成
- 返回服务器代码,跳转到
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
函数中进行的 send 调用相同)。
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
:Energy 主题的主题名称,即/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 的学习,接下来不妨考虑按照以下指南尝试针对其他平台的主题: