你的推送點(diǎn)擊率長(zhǎng)期徘徊在 3% 以下,而業(yè)務(wù)團(tuán)隊(duì)每周都在追問(wèn):“為什么這條活動(dòng)通知沒(méi)有推出去?”——問(wèn)題通常不在文案,而在你選擇的推送通道根本沒(méi)有把消息送到設(shè)備上。

APP 消息推送從來(lái)不是“調(diào)用一個(gè) API 就完事”的功能。它橫跨客戶端長(zhǎng)連接、廠商通道、系統(tǒng)電量管理、通知欄權(quán)限和用戶畫(huà)像標(biāo)簽等多個(gè)斷層帶。本文以 Android 和 iOS 雙端為主,拆解一套可交付的推送工程實(shí)現(xiàn):先確定通道架構(gòu),再落地客戶端對(duì)接與標(biāo)簽體系,最后給出抵達(dá)率排查的硬指標(biāo)。

1. 架構(gòu)決策:自建長(zhǎng)連接 vs 廠商通道,還是兩者混合

消息推送的本質(zhì)是在服務(wù)端與客戶端之間維持一條可觸達(dá)的信道。根據(jù) APP 的前后臺(tái)狀態(tài)和系統(tǒng)限制,這條信道有三種寡頭選項(xiàng)。

自建長(zhǎng)連接??蛻舳送ㄟ^(guò) WebSocket、MQTT 或基于 TCP 的私有協(xié)議維持一條到自家服務(wù)器的持久連接。優(yōu)勢(shì)是完全自主控制消息格式、優(yōu)先級(jí)和重連策略;致命傷是系統(tǒng)對(duì)后臺(tái)進(jìn)程的斬殺。Android 的 Doze 模式、App Standby Buckets 以及 iOS 的后臺(tái)執(zhí)行時(shí)間限制,都讓自建長(zhǎng)連接在用戶退到后臺(tái) 30 分鐘后基本變成“死連接”。因此自建長(zhǎng)連接只適用于前臺(tái)強(qiáng)依賴場(chǎng)景(如即時(shí)通訊應(yīng)用的消息同步),且必須配合前臺(tái)服務(wù)?;睢@會(huì)帶來(lái)耗電警告和上架審核風(fēng)險(xiǎn)。

廠商通道。華為、小米、OPPO、vivo、魅族等 Android 廠商以及蘋(píng)果的 APNs,提供了系統(tǒng)級(jí)的推送信道。它們運(yùn)行在系統(tǒng)進(jìn)程內(nèi),不受應(yīng)用后臺(tái)限制,到達(dá)率普遍在 95% 以上。代價(jià)是每條消息受廠商的配額、速率、格式和長(zhǎng)度約束,且你需要分別對(duì)接每家廠商的 SDK 和控制臺(tái)。

混合通道。工程上的共識(shí)是:Android 端優(yōu)先使用廠商通道,自建長(zhǎng)連接僅用于應(yīng)用前臺(tái)時(shí)的實(shí)時(shí)同步或作為廠商通道的降級(jí)補(bǔ)充;iOS 端統(tǒng)一使用 APNs。你的服務(wù)端需要集成一個(gè)推送路由層,根據(jù)設(shè)備品牌、系統(tǒng)版本、應(yīng)用前后臺(tái)狀態(tài)以及廠商通道的回執(zhí),動(dòng)態(tài)選擇下發(fā)通道。例如,當(dāng)某臺(tái)華為設(shè)備的廠商通道返回“應(yīng)用未啟動(dòng)”時(shí),回退為短信或應(yīng)用內(nèi)拉取通知。

2. 雙端實(shí)現(xiàn)的核心步驟與最小可用對(duì)接

不要試圖一次性對(duì)接所有廠商。先鎖定覆蓋你 80% Android 用戶的 TOP 3 品牌(通常是華為、小米、OPPO/vivo),再逐步補(bǔ)齊。

2.1服務(wù)端:推送路由與消息抽象

服務(wù)端需要定義與廠商無(wú)關(guān)的統(tǒng)一消息模型。最小可用字段如下:

{
  "target": {
    "device_token": "DEVICE_TOKEN",
    "platform": "android",
    "brand": "huawei"
  },
  "payload": {
    "title": "訂單已發(fā)貨",
    "body": "您的訂單#12345 已由順豐發(fā)出",
    "click_action": "open_app",
    "extra": { "order_id": "12345" }
  }
}

推送路由層的職責(zé)是把這份統(tǒng)一消息翻譯為各廠商規(guī)定的請(qǐng)求體。以華為推送為例,你需要使用 Access Token 向 https://push-api.cloud.huawei.com/v3/{appId}/messages:send 發(fā)送如下結(jié)構(gòu):

{
  "message": {
    "notification": {
      "title": "訂單已發(fā)貨",
      "body": "您的訂單#12345 已由順豐發(fā)出"
    },
    "android": {
      "click_action": { "type": 1, "intent": "#Intent;..." }
    },
    "token": ["DEVICE_TOKEN"]
  }
}

路由層還必須處理 token 失效回執(zhí)。當(dāng)廠商返回 InvalidRegistrationNotRegistered 錯(cuò)誤碼時(shí),你應(yīng)當(dāng)在你的用戶設(shè)備表中標(biāo)記該 token 失效,避免后續(xù)繼續(xù)向它推送——否則廠商會(huì)對(duì)你的應(yīng)用降權(quán)。

2.2Android 客戶端:獲取 token 與通知渠道適配

Android 端的接入分為三個(gè)步驟:初始化廠商 SDK,獲取 device token,上報(bào)給服務(wù)端。以小米為例,初始化代碼片段如下:

MiPushClient.registerPush(this, "YOUR_MI_APP_ID", "YOUR_MI_APP_KEY");
MiPushClient.setAlias(this, userId, null);
String token = MiPushClient.getRegId(this);
// 上報(bào) token 到自身服務(wù)端

務(wù)必將 token 與業(yè)務(wù)用戶 ID 綁定,才能實(shí)現(xiàn)分用戶推送。

Android 8.0 起強(qiáng)制要求通知渠道。你必須根據(jù)消息類(lèi)別創(chuàng)建至少一個(gè)渠道,否則通知無(wú)法展示。示例代碼:

NotificationChannel channel = new NotificationChannel(
    "order_channel",
    "訂單通知",
    NotificationManager.IMPORTANCE_HIGH
);
channel.setDescription("訂單狀態(tài)變更與發(fā)貨通知");
notificationManager.createNotificationChannel(channel);

如果消息類(lèi)型超過(guò) 5 種,提前規(guī)劃渠道 ID 枚舉,避免渠道 ID 在迭代中污染用戶設(shè)置頁(yè)面。

2.3iOS 客戶端:APNs 與通知權(quán)限時(shí)機(jī)

iOS 側(cè)使用 APNs 不需要集成第三方廠商 SDK(除非你使用 Firebase Cloud Messaging 等封裝),但你必須在 AppDelegate 中注冊(cè)遠(yuǎn)程通知:

UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
    if granted {
        DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() }
    }
}

收到 device token 后上報(bào)給服務(wù)端:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    // 上報(bào) token 到自身服務(wù)端
}

通知權(quán)限請(qǐng)求時(shí)機(jī)直接決定你的推送權(quán)限開(kāi)啟率。不要在首次冷啟動(dòng)就彈授權(quán)彈窗。應(yīng)當(dāng)在用戶完成關(guān)鍵操作(如第一筆訂單支付成功)后,通過(guò)一個(gè)自建的引導(dǎo)彈窗解釋“開(kāi)啟通知,不錯(cuò)過(guò)發(fā)貨進(jìn)度”,再調(diào)用系統(tǒng)授權(quán)。部分電商類(lèi)應(yīng)用因此將權(quán)限開(kāi)啟率從 40% 提升至 70% 以上。

3. 抵達(dá)率下降的關(guān)鍵排查項(xiàng)與標(biāo)簽體系防退化

推送發(fā)出后進(jìn)入“黑洞”——這是實(shí)現(xiàn)推送功能時(shí)最常遇到的故障模式。你需要逐項(xiàng)檢查以下硬指標(biāo),而不是猜測(cè)。

廠商配額與速率限制。每家廠商都有每日推送量上限和單設(shè)備推送間隔。華為對(duì)非 VIP 應(yīng)用單設(shè)備每分鐘只能接收 1~2 條通知欄消息,超出直接丟棄且不返回錯(cuò)誤。小米對(duì)通知類(lèi)消息有類(lèi)似的風(fēng)控。你必須在路由層加入每個(gè)用戶的頻控計(jì)數(shù)器,合并 30 秒內(nèi)的重復(fù)通知,而不是讓運(yùn)營(yíng)一鍵群發(fā)。

系統(tǒng)級(jí)殺死。Android 用戶手動(dòng)在設(shè)置里“強(qiáng)行停止”應(yīng)用后,廠商通道將無(wú)法啟動(dòng)應(yīng)用進(jìn)程,消息直接丟棄。你的服務(wù)端應(yīng)監(jiān)控 “NotConnected” 類(lèi)錯(cuò)誤碼,并在一定時(shí)間窗口內(nèi)累計(jì)該類(lèi)錯(cuò)誤達(dá)到閾值后,將該設(shè)備標(biāo)記為“不可達(dá)”,轉(zhuǎn)向應(yīng)用內(nèi)消息中心拉取。

Token 沉默替換。應(yīng)用卸載重裝、設(shè)備恢復(fù)出廠設(shè)置、跨手機(jī)遷移都會(huì)導(dǎo)致 token 變化。如果你的客戶端只在首次啟動(dòng)時(shí)上報(bào) token,必然產(chǎn)生大量失效 token。正確做法是監(jiān)聽(tīng) token 刷新回調(diào)(各廠商 SDK 均有提供)并在每次應(yīng)用前臺(tái)進(jìn)入時(shí)重新同步 token 與時(shí)間戳,同時(shí)服務(wù)端對(duì)過(guò)期超過(guò) 90 天未更新的 token 做惰性失效處理。

標(biāo)簽體系退化。推送功能上線半年后,你的用戶標(biāo)簽往往會(huì)因?yàn)槲辞謇矶А热?“30天內(nèi)未活躍” 標(biāo)簽不再更新,導(dǎo)致本該接收促活消息的用戶收到錯(cuò)誤內(nèi)容。你需要為每個(gè)標(biāo)簽定義更新條件與過(guò)期時(shí)間,并在服務(wù)端設(shè)置 Job 每日重算人群包。不要依賴客戶端上報(bào)行為作為唯一標(biāo)簽源,應(yīng)當(dāng)以服務(wù)端事件日志為主,客戶端上報(bào)作為輔助校驗(yàn)。

行動(dòng)建議

如果你正在評(píng)估或重構(gòu)推送功能,按以下順序推進(jìn),避免陷入同時(shí)集成八個(gè)廠商 SDK 的泥潭。

  1. 確定 TOP 3 Android 廠商,只集成華為、小米、OPPO/vivo,并通過(guò)統(tǒng)一路由層接入。iOS 直接使用 APNs。
  2. 建立 token 管理表,包含 device_token、platform、brand、user_id、status(active/expired)、refresh_time,并實(shí)現(xiàn)對(duì)廠商錯(cuò)誤碼的自動(dòng)失效邏輯。
  3. 設(shè)計(jì)通知渠道與權(quán)限引導(dǎo):Android 側(cè)預(yù)定義不多于 6 個(gè)渠道 ID;iOS 側(cè)將授權(quán)彈窗延遲到高價(jià)值行為之后。
  4. 部署頻控與黑名單機(jī)制:同一用戶 60 秒內(nèi)最多接收 1 條營(yíng)銷(xiāo)類(lèi)通知,3 次無(wú)效 token 的錯(cuò)誤碼后自動(dòng)置為 expired。
  5. 監(jiān)控看板:至少展示“下發(fā)量、抵達(dá)量、展示量、點(diǎn)擊量”四個(gè)漏斗節(jié)點(diǎn),并按廠商維度拆分抵達(dá)率。抵達(dá)率低于 85% 的廠商需要優(yōu)先排查配額或 token 有效性。

推送功能的實(shí)現(xiàn)不是一個(gè) API 調(diào)用,而是一套貫穿客戶端、路由層和數(shù)據(jù)治理的基礎(chǔ)能力。把通道可靠性量化,把權(quán)限引導(dǎo)當(dāng)做產(chǎn)品流程來(lái)設(shè)計(jì),你才能讓消息真正抵達(dá)用戶,而不止停留在推送后臺(tái)的“已發(fā)送”數(shù)字上。

← 上一篇 沒(méi)有源代碼,也能重新開(kāi)發(fā)網(wǎng)站嗎?一份務(wù)實(shí)的決策與執(zhí)行框架 下一篇 → 浙江制造型企業(yè)做響應(yīng)式網(wǎng)站,為什么你的移動(dòng)端轉(zhuǎn)化率總是上不去?