获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

关于 FCM 消息

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

Firebase Cloud Messaging (FCM) 提供广泛的消息传递选项和功能。此页面中的信息旨在帮助您了解不同类型的 FCM 消息以及您可以使用它们做什么。

消息类型

使用 FCM,您可以向客户端发送两种类型的消息:

  • 通知消息,有时被认为是“显示消息”。这些由 FCM SDK 自动处理。
  • 由客户端应用程序处理的数据消息。

通知消息包含一组预定义的用户可见键。相比之下,数据消息仅包含用户定义的自定义键值对。通知消息可以包含可选的数据负载。两种消息类型的最大负载均为 4000 字节,但从 Firebase 控制台发送消息时除外,它强制执行 1024 个字符的限制。

使用场景如何发送
通知消息FCM 代表客户端应用程序自动向最终用户设备显示消息。通知消息具有一组预定义的用户可见键和自定义键值对的可选数据负载。
  1. Cloud Functions或您的应用程序服务器等受信任的环境中,使用Admin SDKFCM 服务器协议:设置notification键。可能有可选的数据负载。总是可折叠的。

    查看显示通知和发送请求负载的一些示例

  2. 使用通知编辑器:输入消息文本、标题等,然后发送。通过提供自定义数据来添加可选的数据负载。
数据信息客户端应用程序负责处理数据消息。数据消息只有自定义键值对,没有保留键名(见下文)。Cloud Functions或您的应用程序服务器等受信任的环境中,使用Admin SDKFCM 服务器协议:仅设置data密钥。

当您希望 FCM 代表您的客户端应用处理显示通知时,请使用通知消息。当您想要在客户端应用程序上处理消息时,请使用数据消息。

FCM 可以发送包含可选数据负载的通知消息。在这种情况下,FCM 处理显示通知负载,客户端应用程序处理数据负载。

通知消息

对于测试或营销和用户重新参与,您可以使用 Firebase 控制台发送通知消息。 Firebase 控制台提供基于分析的A/B 测试,以帮助您优化和改进营销信息。

要使用 Admin SDK 或 FCM 协议以编程方式发送通知消息,请使用通知消息的用户可见部分所需的一组预定义键值选项设置notification键。例如,这是一个 IM 应用程序中的 JSON 格式的通知消息。用户可能会看到标题为“葡萄牙对丹麦”和文本为“伟大的比赛!”的消息。在设备上:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
  }
}

当应用程序处于后台时,通知消息会传送到通知托盘。对于前台的应用程序,消息由回调函数处理。

有关可用于构建通知消息的预定义键的完整列表,请参阅参考文档:

数据信息

使用您的自定义键值对设置适当的键,以将数据负载发送到客户端应用程序。

例如,这里是与上面相同的 IM 应用程序中的 JSON 格式消息,其中信息封装在公共data密钥中,客户端应用程序需要解释内容:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    }
  }
}

上面的示例显示了顶级或公共data字段的用法,该字段由接收消息的所有平台上的客户端解释。在每个平台上,客户端应用程序在回调函数中接收数据负载。

数据信息加密

Android 传输层(参见FCM 架构)使用点对点加密。根据您的需要,您可以决定为数据消息添加端到端加密。 FCM 不提供端到端的解决方案。但是,也有可用的外部解决方案,例如毛细管DTLS

带有可选数据负载的通知消息

无论是通过编程方式还是通过 Firebase 控制台,您都可以发送包含自定义键值对的可选负载的通知消息。在通知编辑器中,使用高级选项中的自定义数据字段。

应用程序在接收包含通知和数据负载的消息时的行为取决于应用程序是在后台还是在前台——本质上,它在接收时是否处于活动状态。

  • 在后台时,应用程序在通知托盘中接收通知负载,并且仅在用户点击通知时处理数据负载。
  • 在前台时,您的应用会收到一个消息对象,其中包含两个有效负载。

这是一条 JSON 格式的消息,其中包含notification密钥和data密钥:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    },
    "data" : {
      "Nick" : "Mario",
      "Room" : "PortugalVSDenmark"
    }
  }
}

跨平台自定义消息

Firebase Admin SDK 和 FCM v1 HTTP 协议都允许您的消息请求设置message对象中的所有可用字段。这包括:

  • 一组通用字段,由接收消息的所有应用程序实例解释。
  • 特定于平台的字段集,例如AndroidConfigWebpushConfig ,仅由在指定平台上运行的应用程序实例解释。

特定于平台的块使您可以灵活地为不同平台自定义消息,以确保在收到消息时得到正确处理。 FCM 后端将考虑所有指定参数并为每个平台自定义消息。

何时使用公共字段

在以下情况下使用公共字段:

  • 针对所有平台上的应用程序实例——Apple、Android 和 Web
  • 向主题发送消息

所有应用程序实例,无论平台如何,都可以解释以下公共字段:

何时使用特定于平台的字段

当您需要时使用特定于平台的字段:

  • 仅将字段发送到特定平台
  • 除公共字段外,还发送特定于平台的字段

每当您只想将值发送到特定平台时,请不要使用公共字段;使用特定于平台的字段。例如,要仅向 Apple 平台和 Web 发送通知而不向 Android 发送通知,您必须使用两组不同的字段,一组用于 Apple,一组用于 Web。

当您发送具有特定传递选项的消息时,请使用特定于平台的字段来设置它们。如果需要,您可以为每个平台指定不同的值。然而,即使您想要跨平台设置基本相同的值,您也必须使用特定于平台的字段。这是因为每个平台对该值的解释可能略有不同——例如,生存时间在 Android 上设置为以秒为单位的过期时间,而在 Apple 上则设置为过期日期

示例:具有特定于平台的传递选项的通知消息

以下 v1 发送请求向所有平台发送通用通知标题和内容,但也发送一些特定于平台的覆盖。具体来说,要求:

  • 为 Android 和 Web 平台设置较长的生存时间,同时将 APNs(Apple 平台)消息优先级设置为低设置
  • 设置适当的键来定义用户点击 Android 和 Apple 上的通知的结果——分别click_actioncategory
{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"Match update",
       "body":"Arsenal goal in added time, score is now 3-0"
     },
     "android":{
       "ttl":"86400s",
       "notification"{
         "click_action":"OPEN_ACTIVITY_1"
       }
     },
     "apns": {
       "headers": {
         "apns-priority": "5",
       },
       "payload": {
         "aps": {
           "category": "NEW_MESSAGE_CATEGORY"
         }
       }
     },
     "webpush":{
       "headers":{
         "TTL":"86400"
       }
     }
   }
 }

有关消息正文中特定于平台的块中可用密钥的完整详细信息,请参阅HTTP v1 参考文档。有关构建包含消息正文的发送请求的更多信息,请参阅构建发送请求

交付选项

FCM 为发送到 Android 设备的消息提供了一组特定的传递选项,并允许在 Apple 平台和 Web 上使用类似的选项。例如,“可折叠”消息行为在 Android 上通过 FCM 的collapse_key支持,在 Apple 上通过apns-collapse-id支持,在 JavaScript/Web 上通过Topic支持。具体请参见本节说明及相关参考文档。

不可折叠和可折叠消息

不可折叠的消息表示每条单独的消息都被传送到设备。不可折叠的消息提供一些有用的内容,这与可折叠的消息相反,例如向移动应用程序发送无内容的“ping”以联系服务器以获取数据。

不可折叠消息的一些典型用例是聊天消息或关键消息。例如,在 IM 应用程序中,您可能希望传送每条消息,因为每条消息都有不同的内容。

对于 Android,最多可存储 100 条消息而不会折叠。如果达到限制,所有存储的消息都将被丢弃。当设备重新联机时,它会收到一条特殊消息,表明已达到限制。然后应用程序可以正确处理这种情况,通常是通过请求应用程序服务器的完全同步。

可折叠消息是在尚未传送到设备时可以由新消息替换的消息。

可折叠消息的一个常见用例是用于告诉移动应用程序从服务器同步数据的消息。一个例子是用最新分数更新用户的体育应用程序。只有最近的消息是相关的。

要在 Android 上将消息标记为可折叠,请在消息负载中包含collapse_key参数。默认情况下,折叠键是在 Firebase 控制台中注册的应用程序包名称。 FCM 服务器可以为每个设备同时存储四个不同的可折叠消息,每个消息都有不同的折叠键。如果超过此数量,FCM 仅保留四个折叠键,不保证保留哪些。

默认情况下,没有有效负载的主题消息是可折叠的。通知消息始终是可折叠的,并且会忽略collapse_key参数。

我应该使用哪个?

从性能的角度来看,可折叠消息是更好的选择,前提是您的应用不需要使用不可折叠消息。但是,如果您使用可折叠消息,请记住,在任何给定时间,FCM 只允许每个注册令牌最多使用四个不同的折叠密钥。不能超过这个数量,否则会造成不可预知的后果。

使用场景如何发送
不可折叠每条消息对客户端应用程序都很重要,需要传递。默认情况下,除通知消息外,所有消息都是不可折叠的。
可折叠当有较新的消息呈现与客户端应用程序无关的较旧的相关消息时,FCM 会替换较旧的消息。例如:用于从服务器启动数据同步的消息,或过时的通知消息。在消息请求中设置适当的参数:
  • Android 上的collapseKey
  • Apple 上apns-collapse-id
  • 网络Topic
  • 遗留协议中的collapse_key (所有平台)

设置消息的优先级

您有两个选项可以为下游消息分配传递优先级:正常优先级和高优先级。虽然跨平台的行为略有不同,但正常和高优先级消息的传递是这样的:

  • 正常优先级。当应用程序在前台时,普通优先级消息会立即传递。对于后台应用程序,交付可能会延迟。对于时间敏感度较低的消息,例如新电子邮件通知、保持 UI 同步或在后台同步应用程序数据,请选择正常传递优先级。

  • 高优先级。即使设备处于打盹模式,FCM 也会尝试立即传递高优先级消息。高优先级消息用于时间敏感的、用户可见的内容。

以下是通过 FCM HTTP v1 协议发送的普通优先级消息示例,用于通知杂志订阅者有新内容可供下载:

{
  "message":{
    "topic":"subscriber-updates",
    "notification":{
      "body" : "This week's edition is now available.",
      "title" : "NewsMagazine.com",
    },
    "data" : {
      "volume" : "3.21.15",
      "contents" : "http://www.news-magazine.com/world-week/21659772"
    },
    "android":{
      "priority":"normal"
    },
    "apns":{
      "headers":{
        "apns-priority":"5"
      }
    },
    "webpush": {
      "headers": {
        "Urgency": "high"
      }
    }
  }
}

有关设置消息优先级的更多特定于平台的详细信息:

设置消息的生命周期

FCM 通常会在消息发送后立即进行传递。然而,这并不总是可能的。例如,如果平台是 Android,则设备可能已关闭、离线或不可用。或者 FCM 可能会故意延迟消息,以防止应用消耗过多资源并对电池寿命产生负面影响。

发生这种情况时,FCM 会存储消息并在可行时尽快传送它。虽然这在大多数情况下都很好,但对于某些应用程序来说,迟交的消息可能永远不会送达。例如,如果消息是来电或视频聊天通知,则它仅在通话终止之前的一小段时间内有意义。或者,如果该消息是活动邀请,则在活动结束后收到也是无用的。

在 Android 和 Web/JavaScript 上,您可以指定消息的最长生命周期。该值的持续时间必须介于 0 到 2,419,200 秒(28 天)之间,并且对应于 FCM 存储和尝试传递消息的最长时间。不包含此字段的请求默认为最长四个星期。

以下是此功能的一些可能用途:

  • 视频聊天来电
  • 即将到期的邀请活动
  • 日历事件

指定消息生命周期的另一个优点是 FCM 从不限制生存时间值为 0 秒的消息。换句话说,FCM 保证必须“现在或永不”传递的消息尽最大努力。请记住, time_to_live值为 0 意味着无法立即传送的消息将被丢弃。但是,由于此类消息从不存储,因此这为发送通知消息提供了最佳延迟。

以下是包含 TTL 的请求示例:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "data":{
      "Nick" : "Mario",
      "body" : "great match!",
      "Room" : "PortugalVSDenmark"
    },
    "apns":{
      "headers":{
        "apns-expiration":"1604750400"
      }
    },
    "android":{
      "ttl":"4500s"
    },
    "webpush":{
      "headers":{
        "TTL":"4500"
      }
    }
  }
}

消息的生命周期

当应用程序服务器向 FCM 发布消息并收到返回的消息 ID 时,并不意味着消息已经传送到设备。相反,这意味着它已被接受交付。消息被接受后会发生什么取决于许多因素。

在最好的情况下,如果设备连接到 FCM,屏幕亮着并且没有节流限制,消息会立即传递。

如果设备已连接但处于打瞌睡状态,则 FCM 会存储一条低优先级消息,直到设备退出打瞌睡状态。这就是collapse_key标志发挥作用的地方:如果已经有一条消息具有相同的折叠密钥(和注册令牌)存储并等待传递,则旧消息将被丢弃,新消息将取代它(即旧消息消息被新消息折叠)。但是,如果未设置折叠键,则会存储新消息和旧消息以供将来传递。

如果设备未连接到 FCM,则会存储消息,直到建立连接(再次遵守折叠键规则)。建立连接后,FCM 会将所有未决消息传送到设备。如果设备再也没有连接(例如,如果它恢复出厂设置),消息最终会超时并从 FCM 存储中丢弃。默认超时为四个星期,除非设置了time_to_live标志。

要更深入地了解消息的传递:

    要更深入地了解 Android 或 Apple 平台上的消息传递,请参阅FCM 报告仪表板,它记录了在 Apple 和 Android 设备上发送和打开的消息数量,以及“印象”(用户看到的通知)的数据安卓应用程序。

对于启用直接通道消息传递的 Android 设备,如果设备超过 1 个月未连接到 FCM,FCM 仍会接受消息但会立即丢弃它。如果设备在您发送给它的最后一条数据消息后的四个星期内连接,您的客户端将收到onDeletedMessages()回调。然后应用程序可以正确处理这种情况,通常是通过请求应用程序服务器的完全同步。

最后,当 FCM 尝试向设备发送消息并且应用已卸载时,FCM 会立即丢弃该消息并使注册令牌无效。以后尝试向该设备发送消息会导致NotRegistered错误。

节流和缩放

我们的目标是始终传递通过 FCM 发送的每条消息。然而,传递每条消息有时会导致糟糕的整体用户体验。在其他情况下,我们需要提供边界以确保 FCM 为所有发送者提供可扩展的服务。

可折叠消息节流

如上所述,可折叠消息是无内容的通知,旨在相互折叠。如果开发人员过于频繁地向应用程序重复相同的消息,我们会延迟(节流)消息以减少对用户电池的影响。

例如,如果您向单个设备发送大量新电子邮件同步请求,我们可能会将下一个电子邮件同步请求延迟几分钟,以便设备可以以较低的平均速率同步。严格执行此节流以限制用户体验的电池影响。

如果您的用例需要高突发发送模式,那么不可折叠消息可能是正确的选择。对于此类消息,请确保包含此类消息中的内容,以降低电池成本。

我们将可折叠消息限制为每台设备每个应用程序突发 20 条消息,每 3 分钟重新填充 1 条消息。

XMPP 服务器节流

我们将您可以连接到 FCM XMPP 服务器的速率限制为每个项目每分钟 400 个连接。这不应该是消息传递的问题,但对于确保我们系统的稳定性很重要。

对于每个项目,FCM 允许 2500 个并行连接。

单个设备的最大消息速率

对于 Android,您最多可以向单个设备发送 240 条消息/分钟和 5,000 条消息/小时。这个高阈值是为了允许短期的流量爆发,例如当用户通过聊天快速交互时。此限制可防止发送逻辑中的错误无意中耗尽设备上的电池。

对于 iOS,当速率超过 APNs 限制时,我们会返回错误。

上行消息限制

我们将每个项目的上游消息限制为 1,500,000 条/分钟,以避免上游目标服务器过载。

我们将每台设备的上行消息限制为 1,000 条/分钟,以防止电池因不良应用行为而耗尽。

主题消息限制

主题订阅添加/删除速率限制为每个项目 3,000 QPS。

有关消息发送速率,请参阅扇出限制

扇出节流

消息扇出是将消息发送到多个设备的过程,例如当您定位主题和组时,或者当您使用通知编辑器定位受众或用户群时。

消息扇出不是即时的,因此有时您会同时进行多个扇出。我们将每个项目的并发消息扇出数限制为 1,000。之后,我们可能会拒绝额外的扇出请求或推迟请求的扇出,直到一些已经在进行的扇出完成。

实际可实现的扇出率受同时请求扇出的项目数量的影响。单个项目的扇出率为 10,000 QPS 的情况并不少见,但该数字并不能保证,而是系统总负载的结果。重要的是要注意可用的扇出容量在项目之间分配,而不是在扇出请求之间分配。因此,如果您的项目有两个正在进行的扇出,那么每个扇出将只能看到可用扇出率的一半。最大化扇出速度的推荐方法是一次只进行一个活动扇出。

FCM 端口和您的防火墙

如果您的组织有防火墙来限制进出 Internet 的流量,您需要将其配置为允许移动设备与 FCM 连接,以便网络上的设备接收消息。 FCM 通常使用端口 5228,但有时也使用 443、5229 和 5230。

对于连接到您网络的设备,FCM 不提供特定 IP,因为我们的 IP 范围变化太频繁,您的防火墙规则可能会过时,从而影响您的用户体验。理想情况下,白名单端口 5228-5230 和 443 没有 IP 限制。但是,如果您必须有 IP 限制,则应将goog.json中列出的所有 IP 地址列入白名单。这个大列表会定期更新,建议您每月更新一次规则。由防火墙 IP 限制引起的问题通常是间歇性的并且难以诊断。

我们确实提供了一组可以列入白名单的域名,而不是 IP 地址。这些主机名列在下面。如果我们开始使用其他主机名,我们将在此处更新列表。在防火墙规则中使用域名可能在您的防火墙设备中起作用,也可能不起作用。

要打开的 TCP 端口:

  • 5228
  • 5229
  • 5230
  • 443

要打开的主机名:

  • mtalk.google.com
  • mtalk4.google.com
  • mtalk-staging.google.com 网站
  • mtalk-dev.google.com
  • alt1-mtalk.google.com
  • alt2-mtalk.google.com
  • alt3-mtalk.google.com
  • alt4-mtalk.google.com
  • alt5-mtalk.google.com
  • alt6-mtalk.google.com
  • alt7-mtalk.google.com
  • alt8-mtalk.google.com
  • android.apis.google.com
  • device-provisioning.googleapis.com
  • firebaseinstallations.googleapis.com

网络地址转换和/或状态包检测防火墙:

如果您的网络实施网络地址转换 (NAT) 或状态数据包检测 (SPI),请为我们通过端口 5228-5230 的连接实施 30 分钟或更长时间的超时。这使我们能够提供可靠的连接,同时减少用户移动设备的电池消耗。

证书

根据您实施的 FCM 功能,您可能需要 Firebase 项目的以下凭据:

项目编号Firebase 项目的唯一标识符,用于对 FCM v1 HTTP 端点的请求。该值在Firebase 控制台的“设置”窗格中可用。
注册令牌

标识每个客户端应用程序实例的唯一令牌字符串。单个设备和设备组消息传递需要注册令牌。请注意,注册令牌必须保密。

发件人ID创建 Firebase 项目时创建的唯一数值,可在 Firebase 控制台设置窗格的云消息传递选项卡中找到。发件人 ID 用于标识可以向客户端应用程序发送消息的每个发件人。
访问令牌一个短暂的 OAuth 2.0 令牌,用于授权对 HTTP v1 API 的请求。此令牌与属于您的 Firebase 项目的服务帐户相关联。要创建和轮换访问令牌,请按照授权发送请求中描述的步骤进行操作。
服务器密钥(用于旧协议)

授权您的应用服务器访问 Google 服务的服务器密钥,包括通过 Firebase 云消息传递旧版协议发送消息。您在创建 Firebase 项目时获取服务器密钥。您可以在 Firebase 控制台设置窗格的云消息传递选项卡中查看它。

重要提示:不要在客户端代码中的任何位置包含服务器密钥。此外,请确保仅使用服务器密钥来授权您的应用服务器。 Android、Apple 平台和浏览器密钥被 FCM 拒绝。