uni-app 离线推送
更新时间: 2024/03/14 19:21:14
为了提高消息送达率,云信引入手机系统厂商推送。目前支持的厂商包括小米、华为、vivo、OPPO、魅族、谷歌 FCM。暂不支持荣耀推送。
功能概览
NIM SDK 支持离线推送消息功能。
当用户清理掉应用进程(被冻结、主动关闭)、网络不稳定等导致客户端 SDK 无法与云信服务器保持正常连接时,将使用手机厂商系统级推送来告知用户有消息需要接收。
您可以通过集成各手机厂商推送 SDK,与 NIM SDK 搭配使用,实现离线推送功能。
前提条件
在实现离线推送功能之前,请确保:
-
Android 开发环境满足如下要求:
- Android 4.4 及以上版本
- 自 v6.9.0 起,改用 AndroidX 支持库,Target API 改为 28,不再支持 support 库
-
iOS 开发环境满足如下要求:
- Xcode 13
- iOS 9.0.0 及以上版本
实现步骤
步骤 1:上传推送证书至云信控制台
- 在第三方推送平台注册应用(获取应用信息),并开启推送服务。
- 将获取到的应用信息和推送证书上传至云信控制台,完成第三方推送服务与云信服务的通信。
具体信息参见实现 Android 离线推送和实现 APNs 离线推送的步骤 1。
步骤 2:设置 uni-app 工程
-
新建 uni-app 工程,并引入云信 uni-app 插件。
在您的 uni-app 应用根目录下新建 nativeplugins 文件夹,然后将下载的插件置于 nativeplugins 文件夹下。如下图所示:
- 华为注册厂商推送服务时,包含 agconnect-services.json 文件。开发者需下载该文件,并将其放至您的 uni-app 应用根目录下的 nativeplugins/NIMUniPlugin/android/assets 文件夹下。
-
配置 uni-app 支持推送。选择 App 模块配置,勾选 Push(消息推送)。
不要勾选 “uniPush 1.0” 或者 “uniPush 2.0”。
-
添加推送插件。
选择本地插件(NIMUniPlugin)并填入第三方厂商的推送鉴权字段。
vivo 的应用信息还需要在插件参数中配置(如下图所示),其它厂商不需要。
-
构建自定义基座。
自定义基座是 uni-app 程序运行的底层原生环境。由于使用了原生层插件,因此需要打包自定义基座,并再基于自定义基座运行。
打包自定义基座时,需要提供安卓/苹果平台签名证书。安卓平台签名证书是开发者后续更新升级已发布 APK 的凭证。开发者需要自行生成证书文件并保管,具体请参考生成安卓平台签名证书和生成 iOS 证书。
-
在 HBuilderX 中打开当前项目,选择运行 -> 运行到手机或模拟器 -> 制作自定义调试基座。
-
在弹窗中填写以下信息:
Android 自定义基座打包的信息- Android 包名:必填,您的 android 应用包名
- 证书别名:必填,生成打包证书时填入的 alias
- 证书私钥密码:必填
- 证书文件:必填
- 选择传统打包
iOS 自定义基座打包的信息- bundleId:必填,您的 iOS 应用的 bundleId
- 证书私钥密码:必填
- 证书profile文件:必填
- 私钥证书:必填
- 选择传统打包
-
打包过程需要 DCloud 账户和一些插件,按照提示运行即可。一般打包需要 5-20 分钟(取决于排队时间)。
-
-
在真机运行。
-
插入真机,选择开发者模式,并允许 USB 安装调试。
-
打开 HBuilderX,选择运行 -> 运行到手机或模拟器 -> 选择 Android/iOS 基座运行。
-
选择自定义基座运行应用。
-
步骤 3:实现离线推送
-
安装并引入 nim-web-sdk-ng。
md
//1.安装 nim-web-sdk-ng npm install nim-web-sdk-ng@latest //2.打开页面 vue 文件,引入 nim uni-app 脚本 const NIMSDK = require('nim-web-sdk-ng/dist/NIM_UNIAPP_SDK')
-
初始化时设置各厂商的推送证书等推送配置。
代码中各个厂商的证书,如
xmCertificateName
、hwCertificateName
等需要和云信控制台中配置的证书名称保持一致。js
const nim = NIMSDK.getInstance({ /** * 使用固定设备ID, */ isFixedDeviceId: true, /** * 其它参数 */ }) const app = getApp() app.globalData.nim = nim const nimPushPlugin = uni.requireNativePlugin('NIMUniPlugin-PluginModule') nim.offlinePush.setOfflinePushConfig({ plugin: nimPushPlugin, authConfig: { xmAppId: "11111", xmAppKey : "22222", xmCertificateName : "XIAOMI_PUSH_CERT", hwAppId : "33333", hwCertificateName : "HUAWEI_PUSH_CERT", oppoAppId: "44444", oppoAppKey: "aaabbb", oppoAppSecret: "cccdddd", oppoCertificateName: "OPPO_PUSH_CERT", /** * 注意vivo的appid和appkey需要同时在此处,以及manifest.json(即插件参数配置)中配置 */ vivoAppId: "55555", vivoAppKey: "eeeffff", vivoCertificateName: "VIVO_PUSH_CERT", fcmCertificateName: "FCM_PUSH_CERT", mzAppId: "66666", mzAppKey: "77778888dddd", mzCertificateName: "MEIZU_PUSH_CERT", apnsCertificateName: "IOS_PUSH_CERT" } }) await nim.connect()
-
在App.vue中,监听应用是否退至后台,并通过 updateAppBackground 告知云信服务器应用状态。
当应用退至后台时,Android 应用仍可以收到 IM SDK 的消息,开发者可以根据这些设置应用通知。而 iOS 则无法激活SDK的回调函数。因此,iOS 退至后台时,应该通过下面代码告知云信服务器,然后云信服务器会给处于后台的 iOS 应用发送离线推送。
onShow: function() { const app = getApp() app && app.globalData.nim && app.globalData.nim.offlinePush.updateAppBackground({ isBackground: false })}, onHide: function() { const app = getApp() app && app.globalData.nim && app.globalData.nim.offlinePush.updateAppBackground({ isBackground: true })}
步骤 4:测试离线推送
消息发送方:
发送消息或自定义系统通知给接收方(离线),具体的收发流程可参见消息收发和自定义系统通知。
这里以发送文本消息为例,通过调用 sendTextMsg
实现。
await nim.msg.sendTextMsg({
"scene": "p2p",
"to": "cs6",
"body": "hello, world",
"pushInfo": {
"needPush": true,
"pushContent": "hello, this is a push content"
}
})
消息接收方:
登录 IM 账户后,杀死应用,或者 iOS 手机退到后台时,能够接收到推送消息。
相关信息
Sample code
推送相关文档
- 第三方厂商推送通道存在流控,具体请参见厂商推送通道限制说明
- 第三方推送厂商通道错误码参考
- 推送 payload 配置
推送注意事项
华为
-
华为应用配置的常规页面包含项目和应用的 Client ID 和 Client Secret,两者对应的参数不一致,请下拉至页面底部,获取应用的 Client ID 和 Client Secret。
-
必须添加打包的 SHA256 证书指纹,SHA256 证书指纹需与自己的打包证书一致。
-
华为注册厂商推送服务时,包含
agconnect-services.json
文件。开发者需下载该文件,并将其放至项目原生插件目录下:nativeplugins/NIMUniPlugin/android/assets/
文件夹下。 -
若修改项目、应用信息、开发服务设置,都需要重新下载配置
agconnect-services.json
文件。配置agconnect-services.json
文件后,需要重新构建自定义基座。 -
注意云信业务后台配置证书时,需要使用华为应用的
clientId
和clientKey
。 -
未上架的应用一天只能够接收两条推送。
-
通过透传参数,可以设置消息透传为测试服透传,这样一天能够测试 500 条消息:
nim.msg.sendTextMsg({ "scene": "p2p", "to": "testAccount", "body": "this is a tex23424t 111", "pushInfo": { "pushPayload": '{"pushTitle":"bonjour 2","hwField":{"androidConfig":{"target_user_type":1}}}' } })
VIVO
- 必须在
manifest.json
文件中设置api_key
与app_id
。 - 如果是离线打包,需要在工程的
AndroidManifest.xml
的Application
节点中添加以下代码:<meta-data android:name="api_key" android:value="xxxx" /> <meta-data android:name="app_id" android:value="xxxx" />
- vivo 每日推送限制为 5 条消息。
OPPO
- 每日能够推送用户数量(安卓应用用户数量) * 2 条消息。
- 可以添加测试设备,然后使用私信通道多次推送。
- 如果返回
RegistrationId Invalid
,可以检查下 OPPO 账号是否注册并登录。
FCM
- FCM 只能够通过离线打包方式构建。
- FCM 需要在 Android 工程下添加
google-services.json
文件。
iOS
- 自定义基座的 bundle id 应该与苹果开发者平台中 identifiers 的 bundle id 保持一致。
- 苹果开发者平台设置 identifiers 时,需要打开 Push Notifications。且该 Notification 的证书设置需要和云信服务器的证书一致。
常见问题
Q:触发离线推送的条件是什么?
A:系统切换到后台并且等 app 被系统回收时,或者用户主动关闭 app,才能触发推送条件。因此,若要测试推送问题,请登录后关闭 app,确保满足推送条件。此外,IOS手机如果退至后台前,调用
Q:调用 updatePushToken
报错 Malformed UTF-8 data
?
A: 可能是插件的版本比较旧导致。旧版本插件未进行 cr4 加密。而 JS 代码默认会对 token 进行 cr4 解密。由于无法解密,所以 JS 会报错。
Q: 基座等待长时间后制作失败?
A: 可能是推送证书导致,请检查上传的推送证书是否有误。
Q: Android 平台调用 getDeviceToken
接口未返回 token?
A: 查看 JS 日志,若日志中存在“开始获取设备 token”且不存在"收到了 token",则说明调用 getDeviceToken
未返回结果。您可以打开 Android Studio,新建一个工程,然后查看 Logcat 打印的日志中是否有其他有效的报错信息。
目前导致上述问题可能的原因包括:
- 未选择带有插件的基座导致,即当前运行的基座不包含原生插件
NIMUniPlugin
,请在 manifest 中配置该插件,重新制作包括该原生插件的自定义运行基座。 java.lang.Integer cannot be casted into java.lang.String:
,即各个厂商的推送鉴权信息错误,如果是纯数字,需要加转义符号: ""。- 其他问题,请仔细检查 manifest 中,厂商的推送鉴权信息是否设置,或者是否设置正确。
Q: iOS 平台 DeviceToken
无法获取?
A: 请检查 uniapp 自定义基座的 bundle id 是否和苹果开发者平台中 identifiers 的 bundle id 保持一致。
Q: 服务器推送时,日志显示 MissingProviderToken 异常?
A: 苹果开发者平台设置 identifiers 时,需要打开 Push Notifications。且该 Notification 的证书设置需要和云信服务器的证书一致。
Q: 一条消息收到重复推送?
A: 请在初始化参数重设置 isFixedDeviceId 为 true,避免设备在服务器重复注册
Q:无法收到推送消息?
A:若无法收到推送消息,请优先检查以下情况:
- 检查 SDK 是否已集成最新版本(当前最新版本为 0.14.0)。
- 检查是否对会话开启免打扰。若开启,则接收不到推送通知,请先关闭。
- 检查手机端是否开启应用通知接收权限。若未开启,则接收不到推送通知,请开启。