92、推送服务集成:极光推送、小米推送、华为推送、自定义推送通道

推送服务,说白了就是让App在后台也能跟用户“打招呼”。

我刚开始做推送时,觉得这玩意儿不就是调个SDK嘛。后来踩了坑才发现——不同厂商的推送策略、保活机制、权限要求,简直是八仙过海各显神通。今天咱们就把极光、小米、华为、还有自定义通道,一个一个捋清楚。

为什么需要多通道推送?

Android系统从6.0开始,对后台限制越来越严。到了8.0,后台服务几乎被“阉割”。你想想看,App在后台收不到推送,用户就收不到消息,那体验得多糟糕。

所以行业里搞了个方案:用厂商通道做保底。说白了,就是让手机厂商自己的推送服务来帮你发消息。小米手机用小米推送,华为手机用华为推送,其他手机用极光这类第三方通道。

核心思路: 能走厂商通道就走厂商通道,走不了再走第三方通道。实在不行,自己搞个长连接兜底。

极光推送集成

极光推送(JPush)是国内用得比较多的第三方推送。它最大的好处是——省心。你不需要关心各家厂商的适配,极光帮你做了封装。

集成步骤

  1. 在极光官网注册应用,获取AppKey
  2. 在build.gradle里添加依赖
  3. 在Application里初始化
  4. 注册广播接收器处理消息
// build.gradle
implementation 'cn.jiguang.sdk:jpush:4.8.0'
implementation 'cn.jiguang.sdk:jcore:3.2.0'

// Application
JPushInterface.setDebugMode(true);
JPushInterface.init(this);

// 广播接收器
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
            String message = intent.getStringExtra(JPushInterface.EXTRA_MESSAGE);
            // 处理自定义消息
        }
    }
}

我的经验: 极光的初始化一定要放在Application的onCreate里,而且越早越好。我曾经因为初始化晚了,导致部分华为手机收不到推送,排查了半天才发现是时序问题。

小米推送集成

小米推送,说白了就是给小米手机“开后门”。小米系统对自家推送有最高优先级,App被杀掉也能收到消息。

集成要点

  • 需要在小米开放平台注册应用,获取AppId和AppKey
  • 小米推送的SDK体积比较小,大概200KB左右
  • 支持透传消息和通知栏消息两种模式
// 初始化
MiPushClient.registerPush(this, APP_ID, APP_KEY);

// 注册回调
public class MyPushMessageReceiver extends PushMessageReceiver {
    @Override
    public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
        // 透传消息,不会弹出通知
    }

    @Override
    public void onNotificationMessageClicked(Context context, MiPushMessage message) {
        // 用户点击了通知栏
    }
}

注意: 小米推送的透传消息,在部分MIUI版本上会被系统拦截。我遇到过用户反馈“收不到透传消息”,后来发现是MIUI 12的省电策略搞的鬼。解决方案是引导用户把App加入“无限制”后台白名单。

华为推送集成

华为推送(HMS Push)是华为手机的“亲儿子”。它的优势在于——华为手机即使杀后台,也能通过系统级通道送达消息。

集成流程

  1. 在华为开发者联盟注册应用,配置SHA256指纹
  2. 集成HMS Core SDK
  3. 实现HmsMessageService
// build.gradle
implementation 'com.huawei.hms:push:6.5.0.300'

// 服务类
public class MyHmsMessageService extends HmsMessageService {
    @Override
    public void onNewToken(String token) {
        // 获取推送令牌,上报给服务端
    }

    @Override
    public void onMessageReceived(RemoteMessage message) {
        // 处理收到的消息
        String data = message.getData();
        // 注意:华为推送的data消息,在App前台时才会回调
    }
}

关键点: 华为推送的onMessageReceived在App后台时,只会收到通知栏消息,不会回调透传消息。这一点跟小米推送不一样。我刚开始做的时候没注意,结果后台消息全丢了。

自定义推送通道

有些场景下,第三方和厂商通道都满足不了需求。比如企业内部App、或者需要实时性极高的IM应用。这时候就得自己搞一套推送通道。

实现方案

  • WebSocket长连接: 实时性最好,但耗电
  • MQTT协议: 轻量级,适合物联网和移动端
  • HTTP长轮询: 实现简单,但延迟较高
// 使用OkHttp实现WebSocket
OkHttpClient client = new OkHttpClient.Builder()
    .readTimeout(0, TimeUnit.MILLISECONDS)
    .build();

Request request = new Request.Builder()
    .url("ws://your-server.com/push")
    .build();

WebSocket ws = client.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // 收到推送消息
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        // 断线重连
        reconnect();
    }
});

我的建议: 自定义通道只作为兜底方案。能走厂商通道就走厂商通道,毕竟系统级推送的稳定性和省电效果,是第三方SDK比不了的。我曾经在一个项目中全部用自定义WebSocket,结果用户反馈手机发烫、耗电快,后来切回厂商通道才解决。

多通道统一管理

实际项目中,往往是多个通道并存。这时候需要一个统一的管理层,来协调各个通道的优先级和切换逻辑。

多通道推送架构图 应用层 推送管理层(优先级调度) 华为推送 小米推送 极光推送 EMUI系统 MIUI系统 其他Android系统

优先级策略

设备类型 首选通道 备选通道 兜底通道
华为手机 华为推送 极光推送 自定义WebSocket
小米手机 小米推送 极光推送 自定义WebSocket
其他手机 极光推送 自定义WebSocket

避坑指南: 我曾经在切换通道时,没有处理好token的同步问题。用户从华为手机换到小米手机,推送token没更新,结果消息全发到旧设备上了。解决方案是:每次设备启动时,重新获取所有通道的token,并上报给服务端。

推送消息的格式规范

不管用哪个通道,消息格式最好统一。我习惯用JSON,包含以下几个字段:

{
  "type": "order_update",      // 消息类型
  "title": "订单状态变更",      // 通知标题
  "content": "您的订单已发货",  // 通知内容
  "payload": {                 // 业务数据
    "order_id": "123456",
    "status": "shipped"
  },
  "extra": {                   // 扩展字段
    "channel": "huawei",
    "priority": "high"
  }
}

我的习惯: payload里只放关键业务数据,不要塞大字段。我曾经见过有人把整个订单对象塞进去,结果推送消息超过4KB,直接被厂商通道拦截了。嗯,后来改成只传order_id,客户端再根据id去拉详情。

推送的测试与监控

推送集成完了,怎么测?我一般分三步走:

  1. 前台测试: App在前台时,看能不能收到透传消息
  2. 后台测试: App切到后台,看通知栏能不能弹出
  3. 杀进程测试: 彻底杀掉App,看厂商通道能不能送达

监控方面,建议接入推送的送达率统计。极光和厂商通道都提供了数据上报接口,可以统计到“发送成功”、“送达设备”、“用户点击”三个维度的数据。

总结一下: 推送集成没有银弹。华为手机用华为推送,小米手机用小米推送,其他手机用极光推送,实在不行自己搞个WebSocket兜底。记住一个原则——能用系统通道就用系统通道,别跟系统作对。