如何相容 FCM/APNs Token 直連推播
適用場景
如果您的 App 符合以下情況,本文適用於您:
- App 已直接對接 Google FCM 和 iOS APNs,自身持有 FCM Token 與 APNs Token,按原生推播協定自主推播;
- 歷史版本 App 未整合 EngageLab AppPush SDK,大量存量使用者沒有 EngageLab 的
registration_id,無法透過 建立推播 API 觸達; - 希望在不強制升級 App 的前提下,先把這些存量使用者納入 EngageLab 推播體系,再逐步遷移到 SDK。
方案概覽
EngageLab 為這一場景提供 裝置註冊 API:伺服器端直接提交已持有的 FCM Token 或 APNs Device Token,EngageLab 為其產生唯一關聯的 registration_id。之後即可像 SDK 註冊使用者一樣,透過建立推播 API 按 registration_id 下發訊息,並使用標籤、別名、統計等基於 registration_id 的能力。
flowchart LR
token["您已持有的<br/>FCM / APNs Token"]
register["裝置註冊 API<br/>/v4/devices/token/registration_id"]
regId["registration_id"]
push["建立推播 API<br/>/v4/push"]
device["使用者裝置收到通知"]
token --> register --> regId --> push --> device接入步驟:
- 伺服器端呼叫裝置註冊 API,按平台批次提交 Token(單次 1~500 個),保存回傳的
registration_id與 Token 的對應關係; - 推播時在建立推播 API 的
to.registration_id中填入目標使用者的registration_id; - Token 發生變化(FCM
onNewToken、APNs 重新註冊)時,重新呼叫裝置註冊 API 取得新的registration_id。
接入後一個常見問題是:使用者在手機上點擊通知後,App 會開啟首頁,還是能直接進入訂單詳情等目標頁面?下文以 Android FCM 為例說明。
以下「通知點擊跳轉」部分僅涵蓋 Android 原生 FCM 通知 場景。iOS(APNs Token 註冊)的點擊跳轉不在本文討論範圍內。
通知點擊跳轉:結論
可以實現目標頁跳轉,但不是註冊了 registration_id 之後就自動具備。
- 預設情況下,點擊通知只會開啟 App;
- 具體進入哪個頁面,由您的 App 自身的點擊處理邏輯決定;
- 若要跳轉到目標頁,需要伺服器端在推播請求中指定
intent.url,並由您的 App 提供能夠回應該 action 的 Activity。
裝置註冊 API 只負責建立 FCM Token 與 registration_id 的對應關係,不會給您的 App 增加任何頁面跳轉能力;這類使用者也不會走依賴 EngageLab SDK 的通知點擊中轉邏輯。因此這是一種過渡期方案,長期仍建議遷移到 EngageLab AppPush SDK,詳見文末「長期建議」章節。
預設行為:不設定點擊動作
當推播請求中沒有設定 notification.android.intent 時,EngageLab 下發給 FCM 的通知不攜帶 click_action。此時的點擊表現完全遵循 FCM 的預設行為:
- App 在背景或已被關閉時,通知由 FCM 自動展示,點擊後開啟 App 的啟動 Activity(即
AndroidManifest.xml中宣告為MAIN/LAUNCHER的 Activity); - 最終使用者看到的是首頁、登入頁,還是恢復到之前停留的頁面,取決於您的 App 的啟動邏輯和目前任務堆疊狀態。
因此「預設開啟 App」並不等價於「一定回到首頁」。詳見 Firebase 官方說明:在 Android 應用程式中接收訊息。
實現目標頁跳轉:intent.url → click_action
對應鏈路
EngageLab 伺服器端會把建立推播 API 中 notification.android.intent.url 的值,對應為 FCM 通知的 android.notification.click_action 欄位,再由 Android 系統在您的 App 中尋找能夠匹配該 action 的 Activity。
flowchart LR
pushApi["建立推播 API<br/>notification.android.intent.url"]
fcm["FCM 訊息<br/>android.notification.click_action"]
activity["您的 App<br/>匹配該 action 的 Activity"]
target["業務目標頁<br/>(如訂單詳情)"]
pushApi --> fcm --> activity --> targetclick_action 的官方定義見 FCM AndroidNotification。
步驟一:伺服器端在推播請求中指定 intent.url
按 registration_id 推播時,在 notification.android 中增加 intent.url,並透過 extras 攜帶業務參數:
curl -X POST https://pushapi-sgp.engagelab.com/v4/push \
-u "appKey:masterSecret" \
-H "Content-Type: application/json" \
-d '{
"from": "push",
"to": {
"registration_id": ["13065ffa4e1a6cc91c3"]
},
"body": {
"platform": "android",
"notification": {
"android": {
"title": "訂單已出貨",
"alert": "您的訂單 20260911001 已出貨,點擊查看物流",
"intent": {
"url": "intent:#Intent;action=com.example.app.ORDER_DETAIL;component=com.example.app/com.example.app.OrderDetailActivity;end"
},
"extras": {
"order_id": "20260911001",
"page": "order_detail"
}
}
}
},
"request_id": "order-shipped-20260911001"
}'
關於 intent.url 的取值,需要注意:
- 它是 Android Intent URI 格式(
intent:#Intent;...;end),不是隨意填寫的網頁位址; action是您的 App 自訂的動作名稱,component是套件名稱/Activity 完整類別名稱;- 同一
url中action與component可以只填其一,但建議同時填寫,以便精確命中目標 Activity; - 更多取值類型(開啟首頁、Deeplink 等)見建立推播 API 中 android 通知欄位 的
intent說明。
步驟二:您的 App 提供匹配的 Activity
在 AndroidManifest.xml 中,為目標 Activity 宣告與 intent.url 中 action 一致的 intent-filter:
<activity
android:name=".OrderDetailActivity"
android:exported="true">
<intent-filter>
<action android:name="com.example.app.ORDER_DETAIL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
FCM 展示通知並被點擊後,會以該 action 啟動對應 Activity,並把通知中的 extras 鍵值放入 Intent 的 extras。目標 Activity 中讀取參數並完成業務路由:
class OrderDetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val orderId = intent.getStringExtra("order_id")
if (orderId.isNullOrEmpty()) {
// 缺少參數時回退到訂單列表或首頁
startActivity(Intent(this, MainActivity::class.java))
finish()
return
}
showOrderDetail(orderId)
}
}
若您的 App 已經有統一的路由中轉頁(例如所有通知點擊都先進入 PushRouterActivity,再根據參數分發到具體頁面),可以把 intent.url 的 component 指向該中轉頁,由中轉頁讀取 extras 後再跳轉到訂單詳情等業務頁面,無需為每個業務頁面單獨宣告 action。
注意事項
- 是否需要整合 EngageLab SDK: 不需要。上述鏈路只依賴 FCM 的
click_action機制和您的 App 自身的 Activity 宣告。 - 已有 click_action 處理可重複使用: 如果您的 App 之前直接使用 FCM 推播時已經實現了
click_action處理邏輯,只需把原來的 action 值填入intent.url即可重複使用。 - 沒有 click_action 處理需要補充: 若您的 App 目前只依賴預設開啟行為,需要按「步驟二」增加 Activity 宣告和參數解析邏輯,否則即使伺服器端設定了
intent.url,系統也找不到可回應的 Activity。 - 業務參數透過 extras 傳遞:
intent.url用於決定「開啟哪個頁面」,頁面內展示什麼內容建議透過extras傳遞(如order_id),由目標 Activity 自行解析。 - App 在前景時的表現: App 在前景時,FCM 不會自動展示通知,而是回呼到您的 App 的
onMessageReceived,是否展示通知以及點擊後如何跳轉均由您的 App 自行實現。 - 驗證方法: 聯調時可先用
intent:#Intent;action=android.intent.action.MAIN;end確認通道鏈路正常,再替換為業務 action 驗證目標頁跳轉。
長期建議:儘快遷移到 EngageLab AppPush SDK
裝置註冊 API 定位於相容過渡方案,用於讓歷史版本 App 的存量使用者在未整合 SDK 的情況下也能被觸達,並產生關聯的 registration_id,為後續接入 EngageLab AppPush 的其他能力做準備。它解決的是「能不能推到」的問題,而不是替代 SDK。
我們建議您把它作為遷移策略的一部分,而不是長期方案:
- 新版本 App 整合 EngageLab AppPush SDK: 新使用者透過 SDK 標準註冊取得
registration_id,直接享有完整的通知展示與點擊處理能力。 - 舊版本 App 用直連 Token 過渡: 存量使用者透過裝置註冊 API 註冊的
registration_id繼續推播,兩套體系可以共存,不需要強制合併。 - 隨版本更新逐步收斂: 隨著使用者升級到整合 SDK 的版本,直連 Token 使用者會自然減少,最終統一到 SDK 體系。
相比本文介紹的直連方式,整合 SDK 後:
- 通知點擊跳轉由 SDK 統一處理,
intent.url支援的三種類型(指定 Activity、應用首頁、Deeplink)無需您在 App 側逐個宣告 action 與解析邏輯; - 前景通知展示、通知欄樣式(
builder_id、style、channel_id等)、角標、訊息折疊等欄位才能完整生效; - SDK 會自動上報裝置資訊與點擊等行為,主控台的送達、點擊統計更完整。
整合方式請參考 Android SDK 整合指南 和 iOS SDK 整合指南。










