您的第一条使用 FCM 主题的多播推送消息

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 目录中。请按以下步骤操作,获取起始代码。它包含 StockNewsAppStockNewsServer 两个目录。前者包含起始 Android 应用,后者包含起始服务器端代码。

git checkout fcm-topics-codelab
cd messaging/fcm-topics-codelab/starter

此 Codelab 的完成版本位于 messaging/fcm-topics-codelab/completed 目录下。

创建 Firebase 项目

  1. Firebase 控制台中,点击添加项目,将 Firebase 项目命名为 StockNews,然后点击继续。注意:请记住 Firebase 项目的项目 ID(或点击修改图标设置首选项目 ID)。

fc08f9a7808e4553

  1. 您可以跳过启用 Google Analytics(分析)。在此 Codelab 中,您不需要该代码段。点击继续
  2. 点击 Create project

恭喜!您刚刚创建了 Firebase 项目。现在,您可以点击项目名称进入控制台。

3. 特定于平台的 Firebase 应用配置

启用 Firebase 支持所需的大部分代码更改都签入到您正在处理的项目中。不过,要添加对移动平台的支持,您需要:

  • 在 Firebase 项目中注册所需的平台
  • 下载特定于平台的配置文件,并将其添加到代码中。

在此 Codelab 中,我们将添加一个 Android Firebase 应用。

84e0b3199bef6d8a配置 Android

  1. Firebase 控制台中,选择“设置”齿轮图标左侧导航栏顶部的项目设置,然后在常规页面中点击您的应用下的 Android 图标。

您应该会看到以下对话框:8254fc299e82f528

  1. 要提供的重要值是 Android 软件包名称。将其设置为 com.ticker.stocknews
    1. 此处提供的软件包名称必须与 StockNewsApp 起始代码的 AndroidManifest.xml 中提供的软件包名称相同。如果您想查找或更改它,请按以下步骤操作:
      1. StockNewsApp 目录中,打开文件 app/src/main/AndroidManifest.xml
      2. manifest 元素中,找到 package 属性的字符串值。此值是 Android 软件包名称。
  1. 在 Firebase 对话框中,将复制的软件包名称粘贴到 Android 软件包名称字段中。
  2. 您无需为此 Codelab 提供调试签名证书 SHA-1,因为此应用无法发布。请将此处留空。
  3. 点击注册应用
  4. 还是在 Firebase 控制台中,按照说明下载配置文件 google-services.json
  5. 您可以跳过其余设置步骤,因为起始应用代码中已配置其他所有设置。您会看到您的应用列在 Firebase 控制台的主页面上。
  6. 将刚刚下载的 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 视图,则需要展开项目才能看到相同的内容)

b574ea0089ee87c6

请注意,首次使用时,Android Studio 可能需要几秒钟时间在后台编译项目。在此期间,您会在 Android Studio 底部的状态栏中看到一个旋转图标:

4bc64eb3b99eb0ae

建议您等到此过程完成后再更改代码。这样,Android Studio 就可以提取所有必要的组件。

此外,如果您看到“重新加载以便语言更改生效?”的提示或类似内容,请选择“是”。

模拟器设置

如果您在设置 Android 模拟器方面需要帮助,请参阅运行应用一文。

了解 Android 应用起始代码

  • 起始代码是一个具有极简功能和界面的轻量级 Android 应用。
  • firebase-messaging SDK 的依赖项已添加到 app/build.gradle 文件中。

F04ff8f48d186dff

  • AndroidManifest.xml 中,已添加 MESSAGING_EVENT 回调处理程序。
    • 处理程序 StockNewsMessagingService.java 扩展了 FirebaseMessagingService 类,该类提供各种 Firebase Cloud Messaging 相关功能。如需了解详情,请参阅 FirebaseMessagingService 文档b843c4d33ee53166
    88fad1960f4a6ff5
    • 创建或刷新 FCM 注册令牌时,系统会调用 onNewToken 函数。如需了解详情,请参阅监控令牌生成
    • 收到消息且应用在前台运行时,系统会调用 onMessageReceived 函数。目前,它只记录收到的消息。
  • 此外,AndroidManifest.xml 中还提供了一个名为 StockNewsApplicationAndroid Applicationa4982a8731492dfc.pngccde692f7f68dc5a
    • 此类将是应用启动时要实例化的第一个类。
    • StockNewsApplication 类的 onCreate 函数中,添加了一个 FCM 注册令牌创建调用。它会生成一个有效的 FCM 注册令牌并将其记录在日志中。
  • MainActivity.java 添加了用于显示股票类别选项的 RecyclerView
  • SubscriptionAdapter.java 会实现 RecyclerView.Adapter,以绘制股票类别选择屏幕。
    • 每个股票类别都有一个名称,旁边有一个订阅切换开关。
    • 更改切换开关应该会发出 FCM 主题订阅 / 退订调用。
    • 您将在后面几部分中实现这些调用。
  • model/StockCategories.java 类包含所有库存类别及其关联主题名称的列表。

b32663ec4e865a18.png

运行起始应用

  1. 将 Android 设备连接到计算机或启动模拟器。
  2. 在顶部的工具栏中,选择目标 Android 设备或模拟器,然后按运行按钮。

5b27fc5b237e06b9

  1. 应用界面将如下所示:

ff5b1a1c53231c54.png

  1. 该应用将创建一个 FCM 注册令牌并将其记录在日志中。不过,应用界面中不会有任何变化。
    1. 复制并保存 FCM 注册令牌,因为它将在后续步骤中使用。

927eb66bc909f36b

5. 发送测试消息

现在,您可以将测试消息发送到您在上一步中设置的应用实例。

导入起始服务器代码

启动 IntelliJ IDEA 并打开 messaging/fcm-topics-codelab/starter/StockNewsServer 项目。

左侧导航栏中的项目视图应如下所示:

da20711f6527dff6

请注意,IntellIj IDEA 可能需要几分钟时间来构建您的项目,包括拉取所需的依赖项。

了解服务器起始代码

  • 服务器起始代码是一个基于 Gradle 的 Java 项目。
  • build.gradle 文件中已添加对 firebase-admin SDK 的依赖项。此 SDK 提供对各种 FCM 消息发送功能的访问权限。

650fc733298588f8

  • 最后,还有两个类,即:
    • FcmSender.java:此类包含以下值得注意的方法:
      • initFirebaseSDK:初始化 firebase-admin SDK。
      • sendMessageToFcmRegistrationToken:向 FCM 注册令牌发送消息。
      • sendMessageToFcmTopic:向 FCM 主题发送消息。
      • sendMessageToFcmTopicCondition:向 FCM 主题条件发送消息。
    • FcmSubscriptionManager.java:此类包含允许从服务器端管理主题订阅的方法。
      • initFirebaseSDK:初始化 firebase-admin SDK。
      • subscribeFcmRegistrationTokensToTopic:为 FCM 主题订阅 FCM 注册令牌。
      • unsubscribeFcmRegistrationTokensFromTopic:退订 FCM 主题的 FCM 注册令牌。

设置服务器代码

  1. 首先,我们需要设置一个 Firebase 服务帐号,让 firebase-admin SDK 能够授权调用 FCM API。
    1. 前往 Firebase 控制台,点击左侧导航栏中 Project Overview 旁边的齿轮图标,然后选择 Project settings8c2108d4d7c915e9
    2. 在设置页面中,选择 Service accounts(服务账号),然后点击 Create service account(创建服务账号)。84b128cc5dac0a85
    3. 现在,点击生成新的私钥按钮,系统就会开始自动下载您的密钥文件。
    4. 将密钥文件重命名为 service-account.json,并将其复制到 messaging/fcm-topics-codelab/starter/StockNewsServer/src/main/resources 文件夹中。
    5. FcmSender.javaFcmSubscriptionManager.java 都使用以下代码从类路径加载 service-account.json 文件。8dffbee658e0bdd.png
  2. 此时,服务器代码已准备就绪。从顶部菜单栏中,运行“Build”(构建)->“Build Project”(构建项目)。

发送测试消息

  1. FcmSender.java 中,找到 sendMessageToFcmRegistrationToken 函数,然后将您从运行起始应用部分复制的 FCM 注册令牌插入到 registrationToken 字段中。
  2. main 函数中,仅取消注释 sendMessageToFcmRegistrationToken 函数,然后点击“运行”以执行代码。
    1. 观察如何在 message 对象的 Token 字段中设置 FCM 注册令牌。
    2. 此外,请注意我们是如何使用 FirebaseMessaging 接口的 send API 的。

52e4a3ec3f816473

  1. 这应该会向您在上一步中设置的应用实例发送消息。
  2. 当应用实例在前台运行时,您应该会看到记录的消息内容。

d3540ec1089f97dd

  1. 当应用实例在后台运行时,您会发现消息显示在通知栏中。

31203deca59c03fe

太棒了,您使用了 Firebase Admin SDK 向应用实例发送消息。详细了解如何在服务器中使用 Firebase Admin SDK

6. 实现主题订阅 / 退订

在此步骤中,您将在 Android 应用的 Stock Category(股票类别)切换开关上实现主题订阅和退订操作。

当应用用户切换特定股票类别的开关时,将发出主题订阅或取消订阅调用。

查看代码

  • 找到 Android 应用代码中的 SubscriptionAdapter.java 类,然后找到 RecyclerViewViewHolder 类。

6c0614199e684f6

  • 类构造函数使用 setOnCheckedChangeListener 为订阅切换开关设置监听器。
  • 根据开关切换开关,可分别通过调用 subscribeToStockCategoryunsubscribeFromStockCategory 方法来执行订阅和退订操作。
  • RecyclerView 适配器的 onBindViewHolder 会调用 setData 方法,以将 ViewHolder 与相应的库存类别绑定。

实现主题订阅

  1. 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();
          });
    }

实现主题退订

  1. 同样,在 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();
          });
    }

我们来试试看

  1. 运行应用并切换 Stock Category(股票)选项,以执行 Subscribe(订阅)和 Unsubscribe(退订)操作。这如下所示:

订阅

退订

7. 发送您的第一条主题消息

在此步骤中,您将实现服务器端代码以发送 FCM 主题消息。

实现用于发送主题消息的服务器端集成

  1. 在服务器代码中,跳转到 FcmSender.java 并找到名为 sendMessageToFcmTopic 的方法。

56381dd1b40cde9c

  1. 在第一行中,提供您要向其发送消息的 FCM 主题。
    • 它是格式为 /topics/<Topic Name> 的字符串。例如 /topics/Technology
  2. 在接下来的几行中,创建一个新的 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();
  1. 现在,添加对 FirebaseMessaging 实例的调用以发送消息(与 sendMessageToFcmRegistrationToken 函数中进行的 send 调用相同)。
FirebaseMessaging.getInstance().send(message);
  1. 最后,更新 main 函数并启用仅调用 sendMessageToFcmTopic 函数的功能。

9a6aa08dd7c28898

发送消息并验证接收情况

  1. 在发送主题消息之前,请首先确保您的应用实例订阅了您要发送到的主题。
    1. 翻转相应的切换开关即可完成此操作。例如:
    4668247408377712
  2. 现在,您可以通过执行 FcmSender.javamain 函数来发送主题消息。
  3. 与之前一样,您应该能够在应用实例上观察消息接收情况。
    1. 应用实例位于前台
    c144721399f610fe
    1. 应用实例位于后台
    44efc7dfd57e8e9a
  4. 奖励:请尝试退订要发送到的主题,然后重新发送消息。您会发现,消息未传递到应用实例。

8. 发送您的第一条主题条件消息

通过主题条件功能,您可以向主题组合发送消息,从而提供更具表现力的受众群体定义。

例如,在我们的 StockNews 应用中,请考虑向订阅“技术”或“汽车”主题的一组应用实例发送消息的可能性。例如,如果发生了涉及 Waymo 的重大事件,就可能会发生这种情况。

Topics 允许您使用以下运算符以布尔表达式的形式表示组合

  • && :逻辑 AND。例如,'Technology' in topics && 'Automotive' in topics - 仅定位同时订阅了 Technology 和 Automotive Topics 的应用实例。
  • || : 逻辑 OR。例如,'Technology' in topics || 'Automotive' in topics - 定位订阅了“技术”或“汽车”主题的应用实例。
  • () :用于分组的圆括号。例如,'Technology' in topics && ('Automotive' in topics || 'Energy' in topics) - 仅定位已订阅“技术”以及“汽车”或“能源”主题的应用实例。

详细了解如何构建发送请求以使用此功能。

实现服务器端集成以发送主题条件消息

  1. 返回服务器代码,跳转到 FcmSender.java 并找到名为 sendMessageToFcmTopicCondition 的方法。

3719a86c274522cf.png

  1. 在第一行中,对于 topicCondition 变量,请提供要将消息发送到的主题条件。您可以将其设为:'Technology' in topics && 'Automotive' in topics
  2. 在接下来的几行中,创建一个新的 message 对象(类似于 sendMessageToFcmTopic 函数中定义的对象)。
    1. 不同之处在于,您需要设置 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();
  1. 现在,添加对 FirebaseMessaging 实例的调用以发送消息(与 sendMessageToFcmTopic 函数中进行的 send 调用相同)。
FirebaseMessaging.getInstance().send(message);
  1. 最后,更新 main 函数并启用仅调用 sendMessageToFcmTopicCondition 函数的功能。

db9588d40d2a0da6

发送消息并验证接收情况

  1. 在发送主题消息之前,请首先为应用实例同时订阅“技术”和“汽车”主题,以确保应用实例满足指定的主题条件。
  2. 现在,您可以通过执行 FcmSender.javamain 函数来发送主题消息。
  3. 与之前一样,您应该能够在应用实例上观察消息接收情况。
    1. 应用实例位于前台
    6f612ace15aa6515
    1. 应用实例位于后台
    78044a56ac2359cb.png
  4. 额外提示:您现在可以取消订阅“技术”主题,然后重新发送主题条件消息。您应该会发现,应用实例未收到消息。

9. 要点回顾

我们来快速回顾一下到目前为止所学的知识。

  • 如何从应用实例启动主题订阅 / 退订。
  • 向主题发送消息并验证订阅的应用实例的接收情况。
  • 向主题条件发送消息,并在满足条件的应用实例上验证接收情况。

在下一部分中,您将了解如何为应用实例订阅 / 退订主题,而无需从客户端实例化调用。

c0dc20655d392690.gif

10. 从服务器端管理主题订阅

到目前为止,在此 Codelab 中,所有主题订阅和取消订阅的调用都是从应用实例发起的。

但在某些用例中,您可能需要从服务器端管理主题订阅。例如,您可能希望为现有用户群体的某个子群组订阅新主题,而无需等待应用发布。

在本部分,您将了解如何使用 Firebase Admin SDK 通过从服务器端进行调用来订阅和退订主题的一批 FCM 注册令牌。

实现在服务器端为 FCM 主题订阅 FCM 注册令牌

  1. 在服务器代码中,跳转到 FcmSubscriptionManager.java 类。找到名为 subscribeFcmRegistrationTokensToTopic 的方法。您将在此处实现对 subscribeToTopic API 的调用。

5d5709e7b3cbcb04.png

  1. 让我们为应用实例订阅 Energy 主题。为此,请先为以下两个字段提供数据:
    1. registrationTokens:以英文逗号分隔的字符串列表,表示要为其创建主题订阅的 FCM 注册令牌。
    2. topicName:能源主题的主题名称,即 /topics/Energy
  2. 在接下来的几行代码中,请按以下代码实现调用:
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
        registrationTokens, topicName);
  1. 您可以检查 TopicManagementResponse 来获取一些概要结果统计信息。例如,使用 getSuccessCount 输出成功创建的主题订阅的数量。
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
  1. 最后,在 main 函数中,仅启用对 subscribeFcmRegistrationTokensToTopic 函数的调用。

创建订阅并发送主题消息

  1. 此时,您可以创建主题订阅并向其发送消息。
  2. 执行 FcmSubscriptionManager.java 类的 main 函数。这将创建一个主题订阅。
  3. 现在,设置发送消息所需的代码。与之前类似,
    1. FcmSender.java 中,找到 sendMessageToFcmTopic 函数。
    2. topicName 设为能源主题,即/topics/Energy
    3. 创建一个 Message 对象,并使用 setTopic 将其定位到该主题。
    4. 最后,更新 main 方法以仅启用 sendMessageToFcmTopic 函数。
  4. 执行 FcmSender.javamain 函数。此操作会将消息发送到您的应用实例,您可以按如下方式在应用中进行观察。
    1. 应用实例位于前台
    40ab6cf71e0e4116
    1. 应用实例位于后台
    8fba81037198209e

在服务器端取消 FCM 注册令牌对 FCM 主题的订阅

  1. 如需服务器端主题退订,请使用此 unsubscribeFromTopic API。您需要将相关代码添加到 FcmSubscriptionManager.java 类的 unsubscribeFcmRegistrationTokensFromTopic 函数中。

8d9e8ea9d34016bd.png

  1. 您可以自行练习实现服务器端退订代码并通过发送主题消息验证其效果。

11. 恭喜

恭喜,您已成功使用 FCM 主题向应用实例的子组发送多播消息。这有助于简化您及时将相关内容触达用户的能力。

947def3eb33b1e4a.gif

后续步骤

现在,您已完成此 Codelab,不妨考虑使用以下指南尝试其他平台的主题:

参考文档