使用 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.png配置 Android

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

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

  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 将不会跟踪所有本地更改,您可以点击右上角的忽略X。(您所做的任何更改都不会保存到 Git 代码库中。)

如果您采用 Android 视图,那么在项目窗口的左上角应该会看到如下图所示的内容。(如果您处于 Project 视图,则需要展开项目才能看到相同的内容)

b574ea0089ee87c6.png

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

4bc64eb3b99eb0ae.png

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

此外,如果您看到“Reload for language changes to take effect?”的提示或类似内容,请选择“Yes”。

模拟器设置

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

了解 Android 应用起始代码

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

f04ff8f48d186dff.png

  • AndroidManifest.xml 中,已添加 MESSAGING_EVENT 回调处理程序。
    • 此处理程序 StockNewsMessagingService.java 会扩展 FirebaseMessagingService 类,该类提供各种 Firebase Cloud Messaging 相关功能。如需了解详情,请参阅 FirebaseMessagingService 文档b843c4d33ee53166
    88fad1960f4a6ff5.png
    • 创建或刷新 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.png

请注意,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 控制台,点击左侧导航栏中项目概览旁边的齿轮图标,然后选择项目设置8c2108d4d7c915e9.png
    2. 在设置页面中,选择服务账号,然后点击创建服务账号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. 此时,服务器代码已准备就绪。从顶部菜单栏中依次选择“Run Build”->“Build Project”。

发送测试消息

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

52e4a3ec3f816473

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

d3540ec1089f97dd

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

31203deca59c03fe.png

太棒了,您已使用 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.png

  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 函数中进行的发送调用相同)。
FirebaseMessaging.getInstance().send(message);
  1. 最后,更新 main 函数,并仅允许调用 sendMessageToFcmTopic 函数。

9a6aa08dd7c28898

发送消息并验证接收

  1. 在发送主题消息之前,请首先确保您的应用程序实例订阅了要向其发送的主题。
    1. 只需切换相应的切换开关即可实现此目的。例如:
    4668247408377712.png
  2. 现在,您可以通过执行 FcmSender.javamain 函数来发送主题消息。
  3. 和之前一样,您应该能够在应用实例上观察消息接收情况。
    1. 前台应用实例
    c144721399f610fe
    1. 应用实例位于后台
    44efc7dfd57e8e9a.png
  4. 提示:请尝试退订您发送消息的主题,然后重新发送消息。您会发现消息未传送到应用实例。

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) - 仅定位已订阅“技术”以及“汽车”或“能源”主题的应用实例。

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

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

  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 函数中进行的发送调用相同)。
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,不妨考虑使用以下指南尝试其他平台的主题:

参考文档