Logo Site EngageLab Mark Colored Transparent文件
搜尋

如何相容 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

接入步驟:

  1. 伺服器端呼叫裝置註冊 API,按平台批次提交 Token(單次 1~500 個),保存回傳的 registration_id 與 Token 的對應關係;
  2. 推播時在建立推播 API 的 to.registration_id 中填入目標使用者的 registration_id
  3. 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 --> target

click_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" }'
              
              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 完整類別名稱
  • 同一 urlactioncomponent 可以只填其一,但建議同時填寫,以便精確命中目標 Activity;
  • 更多取值類型(開啟首頁、Deeplink 等)見建立推播 API 中 android 通知欄位intent 說明。

步驟二:您的 App 提供匹配的 Activity

AndroidManifest.xml 中,為目標 Activity 宣告與 intent.urlaction 一致的 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>
              
              <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) } }
              
              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.urlcomponent 指向該中轉頁,由中轉頁讀取 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_idstylechannel_id 等)、角標、訊息折疊等欄位才能完整生效;
  • SDK 會自動上報裝置資訊與點擊等行為,主控台的送達、點擊統計更完整。

整合方式請參考 Android SDK 整合指南iOS SDK 整合指南

Icon Solid Transparent White Qiyu
聯繫銷售