Skip to content

移动端推送通道、长连接与长效保活边界 ​

回到总览:异步后台任务、保活、系统能力
相关模块:Android Foreground Service 深挖(服务类型、通知约束与高版本后台限制) · Doze 深度休眠模式与国内厂商后台限制

一句话定义 ​

移动端推送通道与长效保活是指在 Android 8.0+ 与国内厂商 ROM 严格限制后台常驻进程的背景下,通过将自研 TCP 长连接与厂商系统级推送通道(FCM / 小米 / 华为 / OPPO / vivo Push)相结合,实现高到达率消息下发与合规保活的技术架构。

代码索引 ​

计划补齐的实验:

  • labs/android/host/topics/background-tasks/push-channel-demo/ — FCM 与厂商推送通道回调集成、Socket 心跳包保活与死锁测试

为什么需要 ​

  • 为什么自建 TCP 长连接(Socket)在应用退后台一段时间后无法再收到任何推送消息?
    • 一句话答:应用退后台后,设备进入 Doze 模式或被厂商 ROM 强制挂起 CPU/切断网络,自建 Socket 长连接无法继续维护心跳包,链路随之断开;只有由系统底层服务维持的厂商推送通道(如 FCM 或小米 Push 服务)才能突破限制收到消息。
  • 为什么 10 年 Android 工程师架构设计时要明确“推送通道替代自建保活”?
    • 一句话答:Android 原生黑产级别的多进程拉起与双进程保活在 Android 8.0+ / 12+ 已被系统与厂商完全堵死;放弃黑产保活、全面接入厂商推送通道是保证线上消息到达率的唯一合规解法。

底层机制 ​

1. 混合推送通道分发架构 (Hybrid Push Architecture) ​

text
[App 后台 / 灭屏]
       │
       ├── App 运行在前台/刚退后台 ───► [自建 TCP 长连接 (Socket)] ───► (低延迟,高自定义)
       │
       └── App 彻底退后台 / 进程被杀死 ──► [厂商系统级 Push 通道] ───► (高到达率,系统级透传)
                                              ├── 小米 Push (MiPush)
                                              ├── 华为 Push (HMS)
                                              ├── OPPO / vivo Push
                                              └── 谷歌 FCM (海外)

2. 自建 Socket 心跳包 (Heartbeat) 与智能心跳策略 ​

在 App 处于前台或短时间退后台时,自建 Socket 是性价比最高的通信方式:

  • 固定心跳:每隔 4.5 分钟(防止运营商 NAT 端口映射超时切断)发送一次心跳包。
  • 智能心跳 (Smart Heartbeat):根据当前网络环境(Wi-Fi / 5G / 4G)动态探测 NAT 超时时间,在维持连接的前提下最大程度减少 CPU 唤醒次数与电量消耗。

Android / Flutter / Web / Backend 对照 ​

维度Android 宿主Flutter (Dart)iOS 宿主
系统级推送厂商 Push (小米/华为/vivo) / FCM依赖 firebase_messaging / 极光插件APNs (Apple Push Notification)
透传消息处理FirebaseMessagingServiceFirebaseMessaging.onBackgroundMessageUNNotificationServiceExtension
进程杀死后厂商通道弹系统通知,点击唤醒 App点击系统通知唤醒 FlutterEngineAPNs 弹通知,点击唤醒 App

常见场景 ​

1. 厂商推送 Token 注册与服务端绑定 ​

java
// 华为 / 小米 Push 注册示例
public void initVendorPush(Context context) {
    if (RomUtils.isXiaomi()) {
        MiPushClient.registerPush(context, APP_ID, APP_KEY);
    } else if (RomUtils.isHuawei()) {
        HMSAgent.connect(activity, () -> HMSAgent.Push.getToken(this::onTokenReceived));
    }
}

// 拿到各厂商的 RegId / Token 后,统一上报给自己后台服务器绑定 userId
private void onTokenReceived(String token) {
    ApiServer.bindUserPushToken(userId, token, RomUtils.getDeviceBrand());
}

常见误配、事故后果与排障 ​

1. 事故:Android 8.0+ 上忽略 NotificationChannel 导致透传消息无法展示 ​

  • 误配原因:在 Android 8.0 (API 26) 以上设备上,收到厂商透传消息后弹本地通知,未创建 NotificationChannel。
  • 后果:日志提示 Failed to post notification...,通知被系统静默丢弃,用户完全感知不到推送。
  • 排障与修法:在发送通知前,必须创建并注册 NotificationChannel(设置合理的 Importance 等级)。

与相近概念对比 ​

通道类型延迟时间到达率 (进程被杀后)依赖服务
自建 Socket 长连接极低 (毫秒级)0% (进程被杀即断开)自己的 Server 节点
厂商系统级 Push低 (秒级)99%+小米/华为/vivo 等系统服务
FCM (Firebase)低 (海外)国内 0% / 海外 99%Google Play Services

对应实验 ​

计划补齐的实验:

  • labs/android/host/topics/background-tasks/push-channel-demo/ — FCM 与厂商推送通道回调集成、Socket 心跳包保活与死锁测试

复习检查题 ​

  1. 为什么自建的 TCP Socket 长连接心跳时间通常不能超过 5 分钟?

    答:因为移动运营商的网络网关(GGSN / NAT)维护着内部的 TCP 映射表。为了节省网络资源,如果一个 TCP 链路在一定时间内(通常为 4~5 分钟)没有任何数据包收发,运营商 NAT 映射就会静默超时并切断该连接,此时 Client 侧虽然Socket 状态看似连接,实际上已无法收到任何数据。

  2. 在 Android 8.0+ 设备上,为什么厂商推送通道(如小米 MiPush)在应用进程被杀死后依然能弹出推送通知?

    答:因为厂商推送 SDK 的客户端不是运行在你的 App 进程中,而是集成在 Android 操作系统本身的底层常驻系统服务(如小米的 com.xiaomi.xmsf)中。系统服务由手机厂商的 ROM 保证永久存活,当接收到推送后直接由系统服务弹出 Notification,用户点击通知时才去唤醒或启动目标 App。

速记 ​

  • 通道分工:前台走自建 Socket,后台/死进程靠厂商系统 Push。
  • NAT 防切断:Socket 心跳包间隔控制在 4.5 分钟以内。
  • 8.0 渠道:弹 Notification 必须绑定 NotificationChannel,否则静默丢弃。

站点构建时间:2026/8/24 23:43:17