根本原因在于App进程被杀后JS监听器失效,必须依赖厂商通道拉起App;离线收不到主因是厂商通道配置错误,而非代码问题。

为什么在线推送能立刻收到,离线却收不到?
根本原因在于:App进程被系统杀死后,plus.push 的 JS 层监听器(如 click、receive)全部失效,此时必须依赖厂商通道(华为、小米、OPPO 等)的系统级服务拉起 App 并传递消息。UniPush 本身不直接处理离线逻辑,它只是调度层——在线走个推 SDK,离线自动转给对应厂商通道。所以“离线收不到”,90% 是厂商通道没配通,而不是代码写错了。
华为/小米/OPPO 厂商通道配置最容易卡在哪几步?
不是证书或包名填错,而是三个隐蔽但致命的点:
-
SHA256证书指纹必须和云打包用的签名证书完全一致——很多人本地调试用的是 debug.keystore,但正式打包用的是 DCloud 云端生成的 release 证书,两者指纹不同,华为后台校验失败就静默丢弃消息 - 华为要求在
AppGallery Connect中开通「推送服务」后,还必须手动开启「应用回执状态」并填写回调地址https://thirdrcp-hz.getui.com/hw,否则无法确认消息是否送达,后台会拒绝下发 - 小米通道必须使用透传消息格式,且
intent字符串里的component必须严格匹配你的实际包名 +io.dcloud.PandoraEntry,少一个点或大小写错误,系统就无法拉起 App
点击通知后怎么跳转到指定页面?
离线场景下,JS 层的 plus.push.addEventListener("click", ...) 不会触发——因为 App 还没启动。必须靠原生层把参数带进来,再由 JS 拿到并跳转。关键点有三个:
- 服务端推送时,透传消息的
payload字段必须是合法 JSON 字符串(不能是纯字符串),例如:{"page":"pages/order/detail","id":"123"} - 在
App.vue的onLaunch生命周期里,要主动检查启动参数:uni.getLaunchOptionsSync(),它返回的对象中notification或share字段可能含推送参数(不同厂商位置不同,华为在univerify下,小米在intent解析后) - 拿到参数后不要直接
uni.navigateTo,而要用uni.$on('app-ready', () => { ... })确保 Vue 实例已挂载,否则路由跳转会失败
cid 获取失败或为空怎么办?
plus.push.getClientInfoAsync 返回 clientid 为空,不是代码问题,而是 SDK 尚未完成注册。常见于首次安装、网络不稳定或厂商通道未启用时。别用 setTimeout 死等,正确做法是:
- 监听
plus.push.addEventListener("register", callback)事件,等注册成功后再取 cid - 注册成功回调里才调用
plus.push.getClientInfoAsync,否则大概率为空 - 如果长时间未触发
register,说明厂商通道未生效(比如华为没开推送服务、小米没填 AppID),此时cid永远拿不到,离线推送必然失败


















