更新记录
0.1.3(2026-09-09) 下载此版本
- UTS插件, 支持在uniapp/uniappX 中使用
平台兼容性
uni-app(5.0)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | × | × | × | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
uni-app x(5.0)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | - | √ | 12 | √ | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| √ | √ | √ |
使用 Uni-app 离线推送插件
环信 uni-app 推送插件集成了第三方离线消息推送服务,为开发者提供低延时、高送达、高并发、不侵犯用户个人数据的离线消息推送服务。当客户端断开连接或应用进程被关闭等原因导致用户离线时,即时通讯 IM 会通过第三方消息推送服务向该离线用户的设备推送消息通知。
插件只负责向厂商通道或 APNs 注册、获取推送 Token,并把用户点击系统通知的数据回传给 JS。离线消息由环信服务端经厂商通道下发到系统通知栏,插件不负责展示消息。
目前支持的手机厂商推送服务包括:华为、荣耀、小米、OPPO、vivo、魅族、APNs 和 FCM。
::: tip 提示
当前交付物为 UTS 插件 easemob-push,通过 uni_modules 集成。旧版原生插件 EMPushUniPlugin(nativeplugins + uni.requireNativePlugin)已不再作为推荐接入方式。
:::
前提条件
- 在 环信控制台 注册账号,创建应用。
- 了解环信即时通讯 IM 的使用限制,详见 使用限制。
- 已安装 HBuilderX 3.97.0 及以上版本。
- 业务工程已接入环信 IM SDK:4.0 使用
easemob-websdk的 uni-app 入口(usePlugin(..., 'push'));5.0 使用ChatClient+PushManager(setNativePush)。证书配置、厂商参数和自定义基座两边相同,差别只在 SDK 接入代码。 - 必须使用自定义基座或云打包真机运行。标准基座不包含本插件原生代码。
- 若使用推送模板,你需要在 环信控制台 的 即时通讯 > 基础功能 > 消息 页面激活。激活后,如需关闭推送模板功能,必须联系商务,因为该操作会删除推送模板相关的所有配置。
- 各推送使用的条件:
- 小米推送:在小米 / Redmi 设备上可用;
- 华为推送:在华为设备、老荣耀 EMUI 设备上可用;
- 荣耀推送:在新荣耀 MagicOS 设备上可用;
- 魅族推送:在魅族设备上可用;
- OPPO 推送:在 OPPO / 一加 / realme 设备上可用;
- vivo 推送:在 vivo / iQOO 设备上可用;
- APNs 推送:在苹果设备上可用;
- FCM 推送:在安装了 Google Play 服务的设备上可用,且必须离线打包。
插件在 Android 上按设备品牌选择一条通道。若未配置对应厂商参数,或不满足使用条件,会回退到 NORMAL,此时无法收到厂商离线推送。环信 IM SDK 会通过保活手段尽可能保持与服务器的长连接。
::: warning 注意 本插件不支持 HarmonyOS NEXT、H5 和小程序。华为推送仅支持 Android,不支持 HarmonyOS NEXT。 :::
实现流程
步骤 1:上传推送证书至环信控制台
- 在第三方推送服务后台注册应用,获取应用信息,开启推送服务。
- 在 环信控制台 配置获取到的应用信息,上传推送证书,实现第三方推送服务与环信即时通讯 IM 的通信。
登录控制台后,进入应用管理,打开 增值服务 > 消息推送(或 证书管理),点击 添加推送证书,按厂商填写证书名称并上传证书或密钥。
::: tip 提示
更多详情,参见 Android 离线推送 和 APNs 离线推送。证书名称必须与后续客户端配置中的名称完全一致:4.0 写在 usePlugin 的 config 里,5.0 写在 setNativePush 的 certificates 里。
:::
步骤 2:配置 uni-app 应用支持推送插件
1. 新建 uni-app 工程并引入推送插件
将 easemob-push 放到业务工程的 uni_modules/ 目录下:
你的 uni-app 工程/
├── uni_modules/
│ └── easemob-push/
├── App.vue
├── manifest.json
└── AndroidManifest.xml # Android 厂商参数,见下文
2. 配置 uni-app 项目支持推送
打开 manifest.json,选择 App 模块配置,勾选 Push(消息推送),并把 pushRegisterMode 设为 manual,避免 HBuilderX 内置推送与本插件重复注册。
::: warning 注意 不要勾选 uniPush 1.0 或 uniPush 2.0。 :::
3. 配置 Android 厂商参数
证书名称只用于环信侧绑定。厂商 SDK 还需要在宿主工程写入 AppId / AppKey / 证书文件,并保证包名、签名与开放平台一致。
在业务工程根目录创建 AndroidManifest.xml(不是 nativeResources/android/)。云打包会把它合并进最终 APK。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="你的应用包名">
<application>
<!-- 小米:纯数字建议加 push_ 前缀,避免被当成 float -->
<meta-data
android:name="XIAO_MI_APP_ID"
android:value="push_你的小米AppId" />
<meta-data
android:name="XIAO_MI_APP_KEY"
android:value="push_你的小米AppKey" />
<meta-data
android:name="OPPO_APP_KEY"
android:value="你的OPPO_AppKey" />
<meta-data
android:name="OPPO_APP_SECRET"
android:value="你的OPPO_AppSecret" />
<meta-data
android:name="com.vivo.push.app_id"
android:value="你的vivo_AppId" />
<meta-data
android:name="com.vivo.push.api_key"
android:value="你的vivo_AppKey" />
<meta-data
android:name="MEI_ZU_APP_ID"
android:value="push_你的魅族AppId" />
<meta-data
android:name="MEI_ZU_APP_KEY"
android:value="你的魅族AppKey" />
<meta-data
android:name="com.hihonor.push.app_id"
android:value="你的荣耀AppId" />
</application>
</manifest>
package 必须与云打包 / 自定义基座使用的 Android 包名一致。只配置需要的厂商即可。
华为推送额外步骤:
- 从 AppGallery Connect 下载当前应用的
agconnect-services.json。 - 放到
nativeResources/android/assets/agconnect-services.json。 - 确认文件中的包名、App ID 与基座签名指纹已在华为后台登记。
::: warning 注意
- 只配环信证书名称、不写厂商原生参数时,设备会回退到
NORMAL,无法收到离线推送。 - 老荣耀 EMUI 设备走华为 HMS,不是荣耀 Push。新荣耀 MagicOS 才使用
com.hihonor.push.app_id。 - 针对华为推送,该插件仅支持 Android 平台,不支持 HarmonyOS NEXT 系统。
:::
FCM:
云打包默认不带 Firebase / GMS。要启用 FCM 必须离线打包,自行加入 firebase-messaging、play-services-base,并把 google-services.json 放到 Android 宿主工程。未加入依赖时插件会跳过 FCM,不会因此崩溃。
4. 配置 iOS 推送
manifest.json勾选 Push 模块,pushRegisterMode设为manual。- 在 Apple Developer 中为 Bundle ID 开启 Push Notifications。
- 自定义基座使用 Development profile,并包含当前测试机 UDID。
- 正式发布使用 Apple Distribution + App Store profile,不需要绑定用户设备。
- 环信控制台上传的 APNs 证书环境必须与当前包一致:开发包用 development,Ad Hoc / App Store 用 production。
推送 entitlement 由 HBuilderX 的 Push 模块和所选 profile 生成,不要在插件内写死 aps-environment。
5. 配置通知点击入口
华为、荣耀、OPPO、vivo 的系统通知默认打开应用,点击数据在目标 Activity 的 Intent extras 中。请在环信推送证书中配置统一入口:
| 厂商 | 控制台字段 | 值 |
|---|---|---|
| 华为 / 荣耀 | Action | com.hyphenate.push.OnClickNotifyActivity |
| OPPO / vivo | Activity | com.hyphenate.push.OnClickNotifyActivity |
| 小米 | 预定义打开应用或自定义点击 | 插件两种都处理 |
| 魅族 | Receiver 或 Activity | 插件处理 onNotificationClicked |
单条消息也可用环信扩展覆盖默认跳转:
huawei_click_actionhonor_click_actionoppo_click_activityvivo_click_activitymeizu_click_activity
6. 生成自定义基座
自定义基座是 uni-app 应用运行的底层原生环境。本插件包含原生代码和厂商 SDK,必须打包自定义基座后才能在真机上验证。
修改厂商参数、包名、证书、签名或原生依赖后,必须重新制作自定义基座。
::: tip 提示 打包自定义基座时,需要提供安卓 / 苹果平台签名证书。安卓平台签名证书是开发者后续更新升级已发布 APK 的凭证,需自行生成并妥善保管。具体请参考 Android 平台签名证书(.keystore)生成指南 和 iOS 证书(.p12)和描述文件(.mobileprovision)申请。
- 配置原生插件后,必须打包自定义基座进行测试。
- FCM 只能够通过离线打包方式构建。
- FCM 需要在 Android 工程下添加
google-services.json文件。 :::
步骤 3:集成 easemob-push 插件
UTS 的 JS 代理只导出函数,不导出插件实例。4.0 和 5.0 都从 @/uni_modules/easemob-push 按需 import 这些函数,但交给 IM SDK 的方式不同。
| 4.0 SDK | 5.0 SDK | |
|---|---|---|
| 包入口 | easemob-websdk/uniApp/Easemob-chat |
easemob-websdk 的 ChatClient + PushManager |
| 交给 SDK 的方法 | 只需 { onRegister } |
只需 { onRegister, unRegister } |
| 证书字段 | MICertificateName 等 |
certificates.xiaomi 等 |
| 绑定入口 | conn.usePlugin({ emPush, config }, 'push') |
pushManager.setNativePush({ plugin, certificates }) |
| 解绑 | conn.unbindPushToken() |
client.logout() 自动解绑,或 pushManager.removePushToken() |
通知点击、权限、角标、清通知栏由宿主直接调插件,不经过 IM SDK。这一部分 4.0 / 5.0 相同。
在 4.0 SDK 中使用
安装并引入 4.0 uni-app SDK:
// 安装环信 4.0 SDK
npm install easemob-websdk
// 在工程中引入 SDK
import websdk from 'easemob-websdk/uniApp/Easemob-chat'
4.0 SDK 只会调用 emPush.onRegister。点击、权限、清通知等由宿主自己调插件,不必塞进 emPush。
import websdk from 'easemob-websdk/uniApp/Easemob-chat'
import {
addNotificationListener,
onRegister,
requestNotificationAuthorization
} from '@/uni_modules/easemob-push'
const conn = new websdk.connection({
appKey: 'xxxxx', // 你的环信 App Key
isFixedDeviceId: true // 推荐使用固定的设备 ID
})
// #ifdef APP-PLUS
conn.usePlugin({
emPush: { onRegister },
config: {
// 必须与环信控制台「证书管理」中上传的名称完全一致
MICertificateName: 'xxxxxx', // 小米推送证书名称
OPPOCertificateName: 'xxxxxx', // OPPO 推送证书名称
HMSCertificateName: 'xxxxxx', // 华为推送证书名称
VIVOCertificateName: 'xxxxxx', // vivo 推送证书名称,常用格式 appId#appKey
HONORCertificateName: 'xxxxxx', // 荣耀推送证书名称
MEIZUCertificateName: 'xxxxxx', // 魅族推送证书名称
APNsCertificateName: 'xxxxxx', // APNs 推送证书名称
FCMCertificateName: 'xxxxxx' // FCM 推送证书名称
}
}, 'push') // 第二个参数为固定值
// #endif
// 退出 IM 登录、多设备互踢时,解绑环信侧 device token
const unbindPushToken = () => {
conn.unbindPushToken()
}
export default {
globalData: {
pushClickPageReady: false,
pendingPushClicks: []
},
onLaunch() {
// #ifdef APP-PLUS
requestNotificationAuthorization((ret) => {
console.log('notification authorization', ret.status)
})
addNotificationListener((payload) => {
// 仅在用户点击系统通知后回调,不表示消息到达
if (getApp().globalData.pushClickPageReady) {
uni.$emit('easemob-push-click', payload)
} else {
getApp().globalData.pendingPushClicks.push(payload)
}
})
// #endif
}
}
首页在 onLoad 中消费冷启动点击,避免页面尚未监听时丢失事件:
onLoad() {
const onClick = (payload) => {
console.log('push click', payload)
}
uni.$on('easemob-push-click', onClick)
const pending = getApp().globalData.pendingPushClicks.splice(0)
pending.forEach(onClick)
getApp().globalData.pushClickPageReady = true
}
::: tip 提示
unRegister() 只注销厂商 SDK,不会解除环信服务端的推送绑定。4.0 退出登录请调用 conn.unbindPushToken()。
:::
4.0 推荐调用时序:
onLaunch:addNotificationListener / requestNotificationAuthorization
→ conn.usePlugin({ emPush: { onRegister }, config }, 'push')
→ conn.open(...)
→ SDK 调用 onRegister,上传 Token 并绑定证书
→ 杀进程后发消息,走厂商 / APNs 离线推送
→ 用户点击通知 → addNotificationListener
→ 退出登录 → conn.unbindPushToken()
不要在退出 IM 后用离线推送验证点击事件,此时用户已解绑。
在 5.0 SDK 中使用
5.0(ChatClient)由可选的 PushManager 管理 Token 注册、证书映射、绑定更新和退出解绑。SDK 只接收 onRegister / unRegister,不包装点击、权限、角标、initPushModule 等 API。
安装并引入 5.0 SDK:
npm install easemob-websdk
import { ChatClient, PushManager } from 'easemob-websdk'
在 App.vue 的 onLaunch 尽早注册通知点击和权限,不要等 ChatClient 初始化或登录:
import {
addNotificationListener,
requestNotificationAuthorization
} from '@/uni_modules/easemob-push'
export default {
globalData: {
pushClickPageReady: false,
pendingPushClicks: []
},
onLaunch() {
// #ifdef APP-PLUS
requestNotificationAuthorization((ret) => {
console.log('notification authorization', ret.status)
})
addNotificationListener((payload) => {
if (getApp().globalData.pushClickPageReady) {
uni.$emit('easemob-push-click', payload)
} else {
getApp().globalData.pendingPushClicks.push(payload)
}
})
// #endif
}
}
首页 onLoad 消费冷启动点击的写法与 4.0 相同。
配置 Token 生命周期时,只把 onRegister、unRegister 交给 PushManager:
import { ChatClient, PushManager } from 'easemob-websdk'
import { onRegister, unRegister } from '@/uni_modules/easemob-push'
const pushManager = new PushManager()
pushManager.setNativePush({
plugin: { onRegister, unRegister },
certificates: {
// 必须与环信控制台「证书管理」中上传的名称完全一致
xiaomi: 'xxxxxx',
oppo: 'xxxxxx',
huawei: 'xxxxxx',
vivo: 'xxxxxx',
honor: 'xxxxxx',
meizu: 'xxxxxx',
apns: 'xxxxxx',
fcm: 'xxxxxx'
}
})
const client = ChatClient.init({
appKey: 'xxxxx',
managers: [pushManager]
})
await client.login({ userId: 'alice', token: 'IM_TOKEN' })
4.0 config 字段与 5.0 certificates 字段对应关系:
4.0 config |
5.0 certificates |
通道 |
|---|---|---|
APNsCertificateName |
apns |
APNs |
FCMCertificateName |
fcm |
FCM |
HMSCertificateName |
huawei |
华为 |
MICertificateName |
xiaomi |
小米 |
MEIZUCertificateName |
meizu |
魅族 |
VIVOCertificateName |
vivo |
vivo |
OPPOCertificateName |
oppo |
OPPO |
HONORCertificateName |
honor |
荣耀 |
可以在登录前或登录后调用 setNativePush():登录前配置会在会话就绪后注册;登录后配置会立即启动。Token 获取和上传在后台进行,不改变 login() 的结果。
同一启用状态下,相同配置重复设置是幂等操作。若要替换插件或证书,必须先成功调用 removePushToken(),再传入新配置。
观察绑定结果(事件不含 Token、IM Token 或插件原始错误文本,不要打印 onRegister 的完整返回值):
pushManager.addEventHandler('native-push', {
onPushTokenBound(event) {
console.log('bound channel', event.channel, event.notifierName)
},
onPushTokenBindFailed(event) {
console.warn('bind failed', event.stage, event.code, event.retryable)
},
onPushTokenRemoveFailed(event) {
console.warn('remove failed', event.code, event.retryable)
}
})
5.0 解绑语义:
await client.logout():SDK 在鉴权上下文清理前限时尝试解绑,随后注销插件;失败不会阻止本地退出。await pushManager.removePushToken():用于应用内「关闭离线通知」。服务端失败时 Promise 拒绝,原配置和绑定状态保持不变。- 手动移除成功后,临时断线或自动重连不会恢复推送。再次调用
setNativePush()才会重新启用。 - 应用进入后台、进程被杀或可恢复断线不会触发解绑。
::: tip 提示
5.0 不要再调用 conn.usePlugin(..., 'push'),也不要组装完整 emPush 对象。unRegister() 仍只注销厂商 SDK;环信侧解绑走 logout() 或 removePushToken()。
:::
5.0 推荐调用时序:
onLaunch:addNotificationListener / requestNotificationAuthorization
→ pushManager.setNativePush({ plugin, certificates })
→ ChatClient.init({ managers: [pushManager] })
→ client.login(...)
→ SDK 调用 onRegister,上传 Token 并绑定证书
→ 杀进程后发消息,走厂商 / APNs 离线推送
→ 用户点击通知 → addNotificationListener(不经过 SDK)
→ 退出登录 → client.logout() // 或应用内关闭推送:removePushToken()
步骤 4:测试离线推送
- 消息接收方使用自定义基座登录 IM 账号。
- 在环信控制台的用户管理中确认该用户已绑定对应推送证书。
- 保持登录并杀掉应用(确保进程退出,且客户端与服务器断开)。
- 使用另一账号向该用户发送消息。
- 设备应弹出系统通知。点击通知后,
addNotificationListener会收到点击数据。 - 4.0 退出后调用
unbindPushToken(),5.0 调用logout()或removePushToken(),再到控制台确认证书绑定已解除。
通道说明
push_type |
通道 | 设备 |
|---|---|---|
| 0 | APNs | iPhone / iPad |
| 1 | FCM | 需离线打包并加入 Firebase 依赖 |
| 2 | 华为 HMS | 华为、老荣耀 EMUI |
| 3 | 小米 | 小米 / Redmi |
| 4 | 魅族 | 魅族 |
| 5 | vivo | vivo / iQOO |
| 6 | OPPO | OPPO / 一加 / realme |
| 7 | 荣耀 | 新荣耀 MagicOS |
| 8 | NORMAL | 未检测到可用厂商配置 |
initPushModule 返回的 pushConfigTypes 是「已配置通道」,不是当前设备选中的通道。当前实际通道以登录后 onRegister 的 push_type 为准。
Android 运行时选择优先级:
- 已配置 FCM,且 APK 中存在 GMS / Firebase 类。
- 当前品牌对应的厂商通道,且 Manifest / assets 参数齐全。
- 以上都不满足,则为
NORMAL。
iOS 固定走 APNs,push_type 为 0。
通知点击数据
addNotificationListener 只在用户点击系统通知后回调,不表示消息到达。
Android payload:
| 字段 | 来源别名 | 说明 |
|---|---|---|
to |
t |
接收方 |
from |
f |
发送方 |
msgId |
m |
消息 ID |
groupId |
g |
群组 ID,单聊可为空 |
ext |
e |
扩展,可能是对象或 JSON 字符串 |
无法识别环信字段时,可能带 providerData 原始数据。
iOS payload: APNs userInfo 的 JSON。结构由服务端推送内容决定,不一定包含上述五个字段。
应用被杀死后点击通知,原生层可能先于页面注册回调。插件会缓存一次点击数据;JS 层仍建议按上文示例做页面级队列。
常见问题
1. 即时通讯 IM 在哪些情况不会发送离线推送通知?
若应用在后台运行,则用户仍为在线状态,即时通讯 IM 不会向用户推送消息通知。
应用在后台运行或手机锁屏等情况,若客户端未断开与服务器的连接,则即时通讯 IM 不会发送离线推送通知。
聊天室消息不支持离线推送。发送消息时若设置为只发在线,也不会触发离线推送。
2. 即时通讯 IM 是否支持多设备离线推送?
你可在 环信控制台 的 证书管理 页面配置多设备推送策略。该策略配置对所有推送通道生效:
- 所有设备离线时,才发送推送消息;
- 任一设备离线时,都发送推送消息。
多端登录时若有设备被踢下线,即使接入了 IM 离线推送,也收不到离线推送消息。
3. 页面显示已配置小米,但当前是华为 / OPPO 手机?
initPushModule 只反映 Manifest 里已经写入的厂商参数。当前设备实际通道看登录后绑定结果,或调试时 onRegister 的 push_type。未写入对应 AppId / AppKey 时会回退到 NORMAL,无法收到离线推送。
4. 改了证书名还是收不到?
证书名只用于环信绑定。同时还要满足:
- Android 已写入对应厂商 AppId / AppKey,华为还需要
agconnect-services.json; - 包名、签名与厂商开放平台、环信证书一致;
- 修改配置后已重新制作自定义基座;
- 用户保持 IM 登录后杀进程,再由另一账号发消息。
5. 标准基座能跑吗?
不能。必须自定义基座或云打包。
6. unRegister 和环信侧解绑有什么区别?
unRegister():注销当前厂商 SDK,不会解除环信服务端绑定。- 4.0:退出 IM 登录调用
conn.unbindPushToken()。 - 5.0:
client.logout()会自动尝试解绑;应用内关闭离线通知调用pushManager.removePushToken()。
7. Android setBadge 无效?
Android 为空实现,仅 iOS 生效。
8. Android 13 及以上收不到通知?
Android 13+ 需要用户同意通知权限。可在启动时调用 requestNotificationAuthorization。用户拒绝后,可调用 openSettingsForNotification 引导其前往系统设置。
9. 旧项目还在用 requireNativePlugin('EMPushUniPlugin')?
请迁移到 uni_modules/easemob-push,按本文「步骤 3」用函数导入。4.0 只把 { onRegister } 交给 usePlugin;5.0 只把 { onRegister, unRegister } 交给 setNativePush。不要同时集成旧原生插件和本 UTS 插件。

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 2646
赞赏 0
下载 12581294
赞赏 1949
赞赏
京公网安备:11010802035340号