Firebase Cloud Messaging (FCM) 提供廣泛的消息傳遞選項和功能。此頁面中的信息旨在幫助您了解不同類型的 FCM 消息以及您可以使用它們做什麼。
消息類型
使用 FCM,您可以向客戶端發送兩種類型的消息:
- 通知消息,有時被認為是“顯示消息”。這些由 FCM SDK 自動處理。
- 由客戶端應用程序處理的數據消息。
通知消息包含一組預定義的用戶可見鍵。相比之下,數據消息僅包含用戶定義的自定義鍵值對。通知消息可以包含可選的數據負載。兩種消息類型的最大負載均為 4000 字節,但從 Firebase 控制台發送消息時除外,它強制執行 1024 個字符的限制。
使用場景 | 如何發送 | |
---|---|---|
通知消息 | FCM SDK 在後台運行時代表客戶端應用程序向最終用戶設備顯示消息。否則,如果收到通知時應用程序正在前台運行,則應用程序的代碼決定行為。通知消息具有一組預定義的用戶可見鍵和自定義鍵值對的可選數據負載。 |
|
數據信息 | 客戶端應用程序負責處理數據消息。數據消息只有自定義鍵值對,沒有保留鍵名(見下文)。 | 在Cloud Functions或您的應用程序服務器等受信任的環境中,使用Admin SDK或FCM 服務器協議:僅設置data 密鑰。 |
如果您希望 FCM SDK 在您的應用程序在後台運行時自動處理顯示通知,請使用通知消息。當您想要使用您自己的客戶端應用程序代碼處理消息時,請使用數據消息。
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
對像中的所有可用字段。這包括:
- 一組通用字段,由接收消息的所有應用程序實例解釋。
- 特定於平台的字段集,例如
AndroidConfig
和WebpushConfig
,僅由在指定平台上運行的應用程序實例解釋。
特定於平台的塊使您可以靈活地為不同平台自定義消息,以確保在收到消息時得到正確處理。 FCM 後端將考慮所有指定參數並為每個平台自定義消息。
何時使用公共字段
在以下情況下使用公共字段:
- 針對所有平台上的應用程序實例——Apple、Android 和 Web
- 向主題發送消息
所有應用程序實例,無論平台如何,都可以解釋以下公共字段:
何時使用特定於平台的字段
當您需要時使用特定於平台的字段:
- 僅將字段發送到特定平台
- 除公共字段外,還發送特定於平台的字段
每當您只想將值發送到特定平台時,請不要使用公共字段;使用特定於平台的字段。例如,要僅向 Apple 平台和 Web 發送通知而不向 Android 發送通知,您必須使用兩組不同的字段,一組用於 Apple,一組用於 Web。
當您發送具有特定傳遞選項的消息時,請使用特定於平台的字段來設置它們。如果需要,您可以為每個平台指定不同的值。然而,即使您想要跨平台設置基本相同的值,您也必須使用特定於平台的字段。這是因為每個平台對該值的解釋可能略有不同——例如,生存時間在 Android 上設置為以秒為單位的過期時間,而在 Apple 上則設置為過期日期。
示例:具有特定於平台的傳遞選項的通知消息
以下 v1 發送請求向所有平台發送通用通知標題和內容,但也發送一些特定於平台的覆蓋。具體來說,要求:
- 為 Android 和 Web 平台設置較長的生存時間,同時將 APNs(Apple 平台)消息優先級設置為低設置
- 設置適當的鍵來定義用戶點擊 Android 和 Apple 上的通知的結果——分別是
click_action
和category
。
{ "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 會替換較舊的消息。例如:用於從服務器啟動數據同步的消息,或過時的通知消息。 | 在消息請求中設置適當的參數:
|
設置消息的優先級
您有兩個選項可以為下游消息分配傳遞優先級:正常優先級和高優先級。雖然跨平台的行為略有不同,但正常和高優先級消息的傳遞是這樣的:
正常優先級。當應用程序位於前台時,會立即發送普通優先級消息。對於後台應用程序,交付可能會延遲。對於時間敏感度較低的消息,例如新電子郵件通知、保持 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" } } } }
有關設置消息優先級的更多特定於平台的詳細信息:
- APNs 文檔
- 設置和管理消息優先級(Android)
- 網頁推送消息緊急度
設置消息的生命週期
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 拒絕。 |