实现离线推送
本文档适用于开发 iOS 和 Android 端应用。
ZEGO 即时通讯(ZIM)支持离线推送消息的功能。例如在“单聊”或“群组聊天”时,如果您的程序在后台被冻结、或被系统或用户杀掉,与 ZEGO 服务后台的长连接超时断开后,此时如果您已接入“离线推送”功能,ZEGO 后台会为目标用户发送离线推送的消息。
开发者可以通过集成 ZPNs SDK,与 ZIM SDK 搭配使用,实现离线推送功能。
方案介绍
ZIM 实现离线推送的方案如下:

-
首先消息接收方(即接收离线消息的用户),开启各厂商的推送通道,向各厂商的推送服务器发送请求,获取 Token。
-
各厂商的推送服务器,将 Token 返回给接收方。
-
接收方生成 PushID,并向 ZIM 服务器发送请求,绑定用户与 PushID 的关系。
开发者如果将 ZPNs SDK 与 ZIM SDK 搭配使用,SDK 内部会自动绑定用户与 PushID 的关系,无需特殊处理;如果单独使用 ZPNs SDK,则需自行对接 ZPNs 服务器、实现绑定逻辑。请注意,同一设备切换 userID 前,请调用 zim.logout 接口,该接口会清除 userID 绑定的 PushID。
-
发送方开始发送消息,消息存储到 ZIM 服务器。
-
ZIM 服务器会确认接收方的客户端是否在线。
-
如果接收方的客户端不在线,ZIM 服务器会将消息转发给 ZPNs 服务器。
-
ZPNs 服务器将离线消息转发给各厂商的推送服务器。
-
各厂商的服务器将消息通过“离线推送”的方式,推送给接收方;接收方登录后(至少登录一次),即可收到离线消息。
前提条件
在实现“离线推送”功能之前,请确保:
- 开发环境满足以下要求:
- HBuilder X 4.2.7 或以上版本。
- iOS 12.0 或以上版本的 iOS 真机设备或模拟器。
- Android 版本不低于 6.0 的 Android 设备或模拟器。如果为真机,请开启“允许调试”选项。
- iOS/Android 设备已经连接到 Internet。
- 已在 ZEGO 控制台 创建项目,获取到了接入 ZIM SDK 服务所需的 AppID、AppSign。ZIM 服务权限不是默认开启的,使用前,请先在 ZEGO 控制台 自助开通 ZIM 服务(详情请参考控制台的 服务配置 - 即时通讯 - 开通服务),若无法开通 ZIM 服务,请联系 ZEGO 技术支持开通。
- 已集成 ZIM SDK,详情请参考 快速开始 - 实现基本收发消息。
实现流程
接入第三方厂商离线推送通道
请参考下列推送集成指南,集成您需要的第三方厂商离线推送 SDK,接入各厂商的离线推送通道。
目前支持 Apple、小米、华为、OPPO、vivo 和 Google FCM 的推送。
云端打包
使用 uni-app x HBuilder 提供的云端打包方式,请参考下列推送集成指南的前提条件,向厂商申请离线推送证书,在 ZEGO 控制台 配置离线推送证书。
完成上述步骤,即可在集成 ZPNs uni-app x SDK 时,自动集成上述厂商的推送 SDK。
集成 ZPNs SDK
(可选)新建项目
- 启动 HBuilderX,选择“文件 > 新建 > 项目”菜单。

- 在出现的表单中,选择 “uni-app” 平台,并勾选 “uni-app x” 后填写项目名称。

- 单击“创建”,即可创建项目。
导入 SDK
以下两种方式可以任选一种导入。
厂商推送设置
- Android 平台部分厂商的特殊配置文件,需要在自定义基座进行云端打包时被打包到 apk 里,所以需要在自己项目根目录下创建 “nativeResources/android” 目录。如下图所示:

- iOS 平台由于 uni-app x 推送限制,需要在 UI 页面主动调用
uni.getPushClientId({})后才能使用推送模块,详情请查看:客户端启用 uni-push2.0、iOS 平台监听推送相关回调。
-
vivo 推送,编辑
uni_modules/zego-zpns-uts/utssdk/app-android/AndroidManifest.xml文件,并传入 api_key 和 app_id,如下额外信息所示:说明如何获取 api_key 和 app_id,请参考 vivo 推送集成指南。
<application> <!-- 配置 vivo --> <meta-data android:name="com.vivo.push.app_id" android:value="填入 app_id" /> <meta-data android:name="com.vivo.push.api_key" android:value="填入 api_key" /> </application> -
华为推送,从华为推送管理平台下载 “agconnect-services.json” 文件,复制到 “nativeResources/android”目录下。
说明如何获取 “agconnect-services.json” 文件,请参考 华为推送集成指南。
-
FCM 推送,从 Google FCM 推送管理平台下载 “google-services.json” 文件,复制到 “nativeResources/android”目录下。
说明如何获取 “google-services.json” 文件,请参考 FCM 推送集成指南。
-
iOS 平台在 UI 页面主动调用
uni.getPushClientId({})。
export default {
onLaunch() {
// #ifdef APP-IOS
// iOS 平台需要使用 推送模块
// UTS 项目由于官网摇树优化,需要调用推送接口才能注册推送模块
uni.getPushClientId({});
// #endif
},
}制作自定义调试基座
uni-app x 官方自定义调试基座使用说明,请参考 使用自定义基座运行。
-
选择 “运行 > 运行到手机或模拟器 > 制作自定义调试基座” 菜单。

-
在弹出的界面中,按照 uni-app 教程,填写相关信息,并单击“打包”进行云打包。

打包成功后,控制台会收到 uni-app 的相关提示。

切换运行基座为自定义调试基座
自定义调试基座,请选择“运行 > 运行到手机或模拟器 > 运行到 Android App 基座 > 使用自定义基座运行”菜单。
使用 ZPNs SDK 注册离线推送功能
-
使用 ZPNsEventHandler 获取回调。
ZPNsEventHandler 类包含了 ZPNs 中各种事件回调的 Function,开发者可通过传入 Function 来接收 ZPNs 中的事件回调,处理 SDK 异常、消息通知回调。
各移动设备厂商对 ZPNsEventHandler 类的回调支持情况如下表所示:
接口名称 接口说明 厂商支持情况 registered 厂商注册“离线推送”的结果回调。厂商注册“离线推送”的结果,会统一在此接口抛出,可通过该回调获取到 PushID。 所有厂商都支持该回调。 notificationArrived 厂商通知展示回调。厂商通知展示回调,统一在此接口抛出。 - 苹果:支持该回调。
- 小米:App 处于前后台状态下才能收到此回调。
- 华为:不支持该回调。
- OPPO:不支持该回调。
- vivo:不支持该回调。
- Google: 不支持该回调。
throughMessageReceived 厂商透传消息回调。各厂商返回的透传消息都会触发该接口,并在此接口抛出通知。 - 苹果:暂不支持该回调
- 小米:不支持该回调。
- vivo:不支持该回调。
- 华为:支持该回调,但请先参考华为官方文档 推送服务 - FAQ - 申请特殊权限 申请 高优先级透传消息权限。
- OPPO:不支持该回调。
- Google:APP 处于前后台状态下才能收到此回调。
使用 ZPNsEventHandler 注册回调示例开发者可以通过监听 registered 回调获取 ZPNs 注册结果,并在该方法触发时打印 PushID。
ZPNs.getInstance().onRegistered((message) => { console.log('[ZPNs] registered.', message) }); ZPNs.getInstance().onNotificationArrived((message) => { console.log('[ZPNs] notificationArrived', message) }); ZPNs.getInstance().onThroughMessageReceived((message) => { console.log('[ZPNs] throughMessageReceived', message) }); -
配置安卓第三方推送通道。
根据前提条件集成的第三方厂商离线推送 SDK,启用各厂商的推送功能,然后调用 setPushConfig 接口,配置第三方推送通道。
说明由于 Google FCM 的推送通道优先度更高,开启后会导致其他安卓厂商的推送通道失效,因此,如果您的 App 在中国大陆上线,请将 enableFCMPush 设置为
false。反之,如果您的 App 运营于海外市场,则将其设置为true。const config: ZPNsConfig = {enableFCMPush: false, enableHWPush: true, enableMiPush: true, enableOppoPush: true, enableVivoPush: true}; ZPNs.setPushConfig(config); -
设置权限
开发者可以根据实际应用需要,设置应用所需权限。
-
iOS:
调用 applyNotificationPermission 接口,向用户申请通知权限。本接口仅第一次调用时生效,请开发者注意调用时机。
ZPNs.getInstance().applyNotificationPermission(); -
Android:
Android 13 及以上的系统版本需要动态请求申请推送权限,可调用 applyNotificationPermission 接口,向用户申请通知权限。本接口仅第一次调用时生效,请开发者注意调用时机。
ZPNs.getInstance().applyNotificationPermission();
-
调用 registerPush 接口注册离线推送。
说明- 在 iOS 端调用 registerPush 接口时,您需要根据打包时选择的证书为 development 还是 description 而提前填写
iOSEnvironment。切换证书时,请更改此枚举。 - 证书为 development 时,
iOSEnvironment为ZPNsEnvironment.Development。 - 证书为 distribution 时,
iOSEnvironment为ZPNsEnvironment.Production。
// 在 iOS 调用 registerPush 接口时,iOSNotificationArrivedConfig 参数可以用来设置普通弹窗推送在前台到达时,是否展示弹窗、角标、声音,若希望不展示可不填。 const config: ZPNsRegisterConfig = { iOSEnvironment:1, // 开发环境 iOSNotificationArrivedConfig: {isPresentAlert:true,isPresentSound:true,isPresentBadge:true} } ZPNs.getInstance().registerPush(config);注册离线推送功能后,可以通过 ZPNsEventHandler 类中的 onRegistered 回调,获取到离线推送的
pushID,向指定设备推送离线消息。 - 在 iOS 端调用 registerPush 接口时,您需要根据打包时选择的证书为 development 还是 description 而提前填写
完整参考代码
// <script>
import { ZPNs, ZPNsConfig, ZPNsRegisterConfig, ZPNsNotificationChannel, ZPNsLocalMessage } from '@/uni_modules/zego-zpns-uts';
export default {
onLaunch() {
// #ifdef APP-IOS
// iOS 平台需要使用 推送模块
// UTS 项目由于官网摇树优化,需要调用推送接口才能注册推送模块
uni.getPushClientId({});
// #endif
},
onShow() {
this.useZPNs();
},
methods: {
useZPNs() {
// 设置为第1套证书,如果有多套证书时(多个App间互相推送)填写对应的序号
const appType = 1;
// Google FCM 和 国内厂商需要区分开,分别打包
// Google FCM 配置
let appConfig: ZPNsConfig = { appType, enableFCMPush: false };
// ZPNs.setPushConfig(appConfig);
// 国内厂商 配置
appConfig: ZPNsConfig = {
appType,
// 填写在各厂商推送管理平台注册的App的信息
enableHWPush: true, hwAppID: '',
enableMiPush: true, miAppID: '', miAppKey: '',
enableOppoPush: true, oppoAppID: '', oppoAppKey: '', oppoAppSecret: '',
enableVivoPush: true, vivoAppID: '', vivoAppKey: '',
};
ZPNs.setPushConfig(appConfig);
const zpns = ZPNs.getInstance();
// 注册回调事件
zpns.onRegistered((res) => console.log(JSON.stringify(res)));
zpns.onNotificationArrived((res) => console.log(JSON.stringify(res)));
zpns.onNotificationClicked((res) => console.log(JSON.stringify(res)));
zpns.onThroughMessageReceived((res) => console.log(JSON.stringify(res)));
// 申请通知权限
zpns.applyNotificationPermission();
const registerConfig: ZPNsRegisterConfig = {
androidEnvironment: 1, // 开发环境
iOSEnvironment: 1, // 开发环境
iOSNotificationArrivedConfig: {
isPresentAlert: true,
isPresentBadge: true,
isPresentSound: true,
}
};
// 注册推送
zpns.registerPush(registerConfig);
}
}
}
// </script> 使用 ZIM SDK 实现离线推送功能
ZIM 支持在发送单聊消息、群组消息和呼叫邀请时使用离线推送功能。
场景 1:发送单聊消息时使用离线推送功能
-
首先开发者需要通过 ZIMPushConfig 对象,设置离线推送标题、内容、以及其他自定义属性。
const pushConfig: ZIMPushConfig = { title: "离线推送标题", content: "离线推送内容", payload: "自定义透传字段,非必填", resourcesID: "资源 ID,非必填", } -
然后通过 ZIMMessageSendConfig 对象的
pushConfig参数,配置离线消息的相关配置等。const sendConfig: ZIMMessageSendConfig = { priority: 2, pushConfig: pushConfig }; -
发送方调用 sendMessage,传入
sendConfig,向接收方发送单聊消息。const toUserID = ''; const messageTextObj: ZIMMessage = { type: 1, message: '文本消息内容' }; zim.sendMessage(messageTextObj, toUserID, 0, sendConfig) .then((res: ZIMMessageSentResult) => { // 发送成功 }) .catch((err: ZIMError) => { // 发送失败 }); -
接收方如果处于离线状态,将会在上线后,接收到发送方之前发送的离线消息。
场景 2:发送群组消息时使用离线推送功能
-
开发者通过 ZIMPushConfig 对象,设置离线推送标题、内容、以及其他自定义属性。
const pushConfig: ZIMPushConfig = { title: "离线推送标题", content: "离线推送内容", payload: "自定义透传字段,非必填", resourcesID: "资源 ID,非必填", } -
然后通过 ZIMMessageSendConfig 对象的
pushConfig参数,配置离线消息的相关配置等。const sendConfig: ZIMMessageSendConfig = { priority: 2, pushConfig: pushConfig }; -
发送方调用 sendMessage,传入 “sentConfig”,向群组内的所有用户发送消息。
const toGroupID = ''; const messageTextObj: ZIMMessage = { type: 1, message: '文本消息内容' }; zim.sendMessage(messageTextObj, toGroupID, 2, sendConfig) .then((res: ZIMMessageSentResult) => { // 发送成功 }) .catch((err: ZIMError) => { // 发送失败 }); -
群组内的用户,如果有人处于离线状态,将会在上线后,接收到发送方之前发送的群组离线消息。
场景 3:发送呼叫邀请时使用离线推送功能
-
开发者通过 ZIMPushConfig 对象,设置离线推送标题、内容、以及其他自定义属性。
const pushConfig: ZIMPushConfig = { title: "离线推送标题", content: "离线推送内容", payload: "自定义透传字段,非必填", resourcesID: "资源 ID,非必填", } -
然后通过 ZIMCallInviteConfig 对象的
pushConfig参数,配置离线消息的相关配置等。const callInviteConfig: ZIMCallInviteConfig = { mode: 0, timeout: 90, extendedData: '', pushConfig: pushConfig } -
发送方调用 callInvite,传入 “callInviteConfig”,发起呼叫邀请。
const invitees = ['xxxx']; // 被邀请人ID列表 zim.callInvite(invitees, callInviteConfig) .then((res: ZIMCallInvitationSentResult) => { const callID = res.callID; // 操作成功 // 此处的 callID 是用户发起呼叫后,SDK 内部生成的 ID,用于唯一标识一次呼叫邀请;之后发起人取消呼叫、被邀请人接受/拒绝呼叫,都会使用此 callID }) .catch((err: ZIMError) => { // 操作失败 }) -
被邀请的用户若处于离线状态,将会收到对应的离线推送,上线后,若呼叫邀请还未结束,将会收到 callInvitationReceived 回调。
注销离线推送
若开发者希望某台设备不再接收离线推送,可通过调用 unRegisterPush 接口注销。注销后,发送弹窗推送、静默推送也将不再生效。
ZPNs.getInstance().unregisterPush();在线调试
集成 ZPNs SDK 和获取 Push ID 后,您可以在 ZEGO 控制台 在线调试 ZIM 离线推送功能,详情请参考控制台的 ZIM 离线推送调试。
如需在厂商控制台自行调试离线推送功能,需先获取对应厂商的推送 Token,Token 可以从各厂商官方开发者控制台 / 平台获取,也可使用 ZIM 离线推送调试 获取厂商 Token。

