向网页/JavaScript 上的主题发送消息

基于其发布/订阅的模式,FCM 主题消息传递功能可让您将消息发送至已经选择加入特定主题的多台设备。您根据需要撰写主题消息,FCM 负责确定发布路径并将消息可靠地传送至正确的设备。

例如,某个本地潮汐预报应用的用户可选择加入“潮汐警报”主题,并接收关于指定区域最佳海水捕捞条件的通知。体育应用的用户可以订阅他们心仪球队的实时比分自动更新。

关于主题,请注意以下事项:

  • 主题消息传递最适合传递天气或其他可通过公开途径获得的信息。
  • 主题消息的优化重心是吞吐量而非延迟。要将消息快速安全地传送到单台设备或小规模设备组,应将消息定位至注册令牌,而非主题。
  • 如果您需要向一个用户的多台设备发送消息,请考虑在这些使用场景中使用设备组消息传递
  • 主题消息传递不限制每个主题的订阅数。但是,FCM 在这些方面有强制限制:
    • 一个应用实例不可订阅超过 2000 个主题。
    • 如果您正在使用批量导入来订阅应用实例,则每次请求仅限订阅 1000 个应用实例。
    • 每个项目新订阅频率的速率受限。如果您在短时间内发送过多订阅请求,FCM 服务器将给出 429 RESOURCE_EXHAUSTED(“已超出配额”)响应。使用指数退避重试。

为客户端应用订阅主题

有了注册令牌和主题名称,您就可以使用 Google Instance ID server API 向相应主题添加相应令牌。请在以下端点调用 Instance ID API,并提供应用实例的注册令牌和主题名称:

 https://iid.googleapis.com/iid/v1/<REGISTRATION_TOKEN>/rel/topics/<TOPIC_NAME>

例如,要为某个应用实例订阅名为“movies”的主题,请从您的服务器将以下 POST 请求发送到端点,然后在授权标头中添加如下所示的服务器 API 密钥:

https://iid.googleapis.com/iid/v1/nKctODamlM4:CKrh_PC8kIb7O...clJONHoA/rel/topics/movies
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

鉴于服务器密钥的敏感性,切勿从客户端发送这种类型的请求。

请求成功则返回 HTTP 200 OK。如需详细了解错误响应及如何发送批量请求,请参阅为应用实例创建关系映射

接收和处理主题消息

FCM 传送主题消息的方式与处理其他下行消息的方式相同。如何处理客户端上的消息,取决于网页的前台/后台状态以及本节介绍的其他因素。

消息的行为取决于相应页面的状态:页面位于前台(获得焦点)、位于后台、隐藏在其他标签页后,还是完全关闭。无论哪种情况,页面都必须处理 onMessage 回调函数;但当页面位于后台时,您可能还需要处理 setBackgroundMessageHandler 或进行配置以显示通知,让用户能够将您的网页应用放到前台。

应用状态 通知 数据 两者
前台 onMessage onMessage onMessage
后台 (Service Worker) SDK 显示的通知 setBackgroundMessageHandler SDK 显示的通知

在网页应用位于前台时处理消息

为接收 onMessage 事件,您的应用必须在 firebase-messaging-sw.js 中定义 Firebase 消息传递 Service Worker。或者,您也可以使用 useServiceWorker 指定一个现有的服务工作器。

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

当您的应用位于前台时(用户当前正在查看您的网页),您可以直接在页面中接收数据和通知有效负载。

// Handle incoming messages. Called when:
// - a message is received while the app has focus
// - the user clicks on an app notification created by a service worker
//   `messaging.setBackgroundMessageHandler` handler.
messaging.onMessage(function(payload) {
  console.log('Message received. ', payload);
  // ...
});

在网页应用位于后台时处理消息

当应用位于后台时,收到的所有消息都会导致在浏览器中显示通知。您可以在从应用服务器发送请求时指定用于此通知的选项(如标题或点击操作),也可以在客户端中使用 Service Worker 进行指定。

在发送请求中设置通知选项

对于从应用服务器发送的通知消息,FCM JavaScript API 支持 click_action 键。通常情况下,此键会被设置在网页应用的某一页面中:

https://fcm.googleapis.com//v1/projects/<YOUR-PROJECT-ID>/messages:send
Content-Type: application/json
Authorization: bearer <YOUR-ACCESS-TOKEN>

{
  "message": {
    "topic": "matchday"
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "https://dummypage.com"
      }
    }
  }
}

如果点击操作指向已在某个浏览器标签页中打开的页面,那么当用户点击通知时,系统会将该标签页放到前台。如果相应页面尚未打开,那么当用户点击通知时,系统会在一个新标签页中打开该页面。

由于数据消息不支持 click_action,因此我们建议您在所有数据消息中添加通知有效负载。或者,您也可以使用 Service Worker 处理通知。

如需详细了解通知消息与数据消息之间的区别,请参阅消息类型

在 Service Worker 中设置通知选项

不管是通知消息还是数据消息,您都可以在 Service Worker 中设置通知选项。首先,在 Service Worker 中初始化您的应用:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

要设置选项,请调用 firebase-messaging-sw.js 中的 setBackgroundMessageHandler。在本示例中,我们设置了针对标题、正文、图标和点击操作的选项。

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  var notificationTitle = 'Background Message Title';
  var notificationOptions = {
    body: 'Background Message body.',
    icon: '/firebase-logo.png'
  };

  return self.registration.showNotification(notificationTitle,
    notificationOptions);
});

构建发送请求

从服务器端向 Firebase 云消息传递主题发送消息,与将消息发送到单台设备或用户组非常相似。应用服务器会使用类似 /topics/yourTopic 的值设置 to 键。开发者可以选择符合以下正则表达式的任何主题名称:"/topics/[a-zA-Z0-9-_.~%]+"

主题 HTTP POST 请求

发送至一个主题:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
  "to" : "/topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}

主题 HTTP 响应

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

主题 XMPP 消息

发送至一个主题:

<message id="">
  <gcm xmlns="google:mobile:data">
{
  "to" : "/topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

主题 XMPP 响应

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

后续步骤

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面