实现 uni-app 离线推送

更新时间: 2024/05/31 16:06:10

为了提高消息送达率,云信引入手机系统厂商推送。目前支持的厂商包括小米、华为、荣耀、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 及以上版本
  • 注册云信 IM 账号,获取 IM 账号和 Token。

实现步骤

步骤 1:上传推送证书至云信控制台

  1. 在第三方推送平台注册应用(获取应用信息),并开启推送服务。
  2. 将获取到的应用信息和推送证书上传至云信控制台,完成第三方推送服务与云信服务的通信。

具体信息参见实现 Android 离线推送实现 APNs 离线推送的步骤 1。

步骤 2:设置 uni-app 工程

  1. 新建 uni-app 工程,并引入云信 uni-app 插件。

    在您的 uni-app 应用根目录下新建 nativeplugins 文件夹,然后将下载的插件置于 nativeplugins 文件夹下。如下图所示:

    • 华为注册厂商推送服务时,包含 agconnect-services.json 文件。开发者需下载该文件,并将其放至您的 uni-app 应用根目录下的 nativeplugins/NIMUniPlugin/android/assets 文件夹下。
    • 荣耀注册厂商推送服务时,包含 mcs-services.json 文件。开发者需下载该文件,并将其放至您的 uni-app 应用根目录下的 nativeplugins/NIMUniPlugin/android/assets 文件夹下。
  2. 配置 uni-app 支持推送。选择 App 模块配置,勾选 Push(消息推送)。

    不要勾选 “uniPush 1.0” 或者 “uniPush 2.0”。

  3. 添加推送插件。

    选择本地插件(NIMUniPlugin)并填入第三方厂商的推送鉴权字段。


    vivo 的应用信息还需要在插件参数中配置(如下图所示),其它厂商不需要。

  4. 构建自定义基座。

    自定义基座是 uni-app 程序运行的底层原生环境。由于使用了原生层插件,因此需要打包自定义基座,并再基于自定义基座运行。

    打包自定义基座时,需要提供安卓/苹果平台签名证书。安卓平台签名证书是开发者后续更新升级已发布 APK 的凭证。开发者需要自行生成证书文件并保管,具体请参考生成安卓平台签名证书生成 iOS 证书


    1. 在 HBuilderX 中打开当前项目,选择运行 -> 运行到手机或模拟器 -> 制作自定义调试基座

    2. 在弹窗中填写以下信息:

      Android 自定义基座打包的信息
      • Android 包名:必填,您的 android 应用包名
      • 证书别名:必填,生成打包证书时填入的 alias
      • 证书私钥密码:必填
      • 证书文件:必填
      • 选择传统打包
      iOS 自定义基座打包的信息
      • bundleId:必填,您的 iOS 应用的 bundleId
      • 证书私钥密码:必填
      • 证书profile文件:必填
      • 私钥证书:必填
      • 选择传统打包
    3. 打包过程需要 DCloud 账户和一些插件,按照提示运行即可。一般打包需要 5-20 分钟(取决于排队时间)。

  5. 在真机运行。

    1. 插入真机,选择开发者模式,并允许 USB 安装调试。

    2. 打开 HBuilderX,选择运行 -> 运行到手机或模拟器 -> 选择 Android/iOS 基座运行

    3. 选择自定义基座运行应用。

步骤 3:实现离线推送

  1. 安装并引入 nim-web-sdk-ng。

    md//1.安装 nim-web-sdk-ng
    npm install nim-web-sdk-ng@">=10"
    //2.打开页面 vue 文件,引入 nim uni-app 脚本
    const NIMSDK = require('nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK') 
    
  2. 初始化时设置各厂商的推送证书等推送配置。

    代码中各个厂商的证书,如 xmCertificateNamehwCertificateName 等需要和云信控制台中配置的证书名称保持一致。

    jsconst nim = NIMSDK.getInstance(param1, {
        /**
         * 设置固定设备id。这样 IM 推送服务可以绑定当前设备
         */
        V2NIMLoginServiceConfig: {
            isFixedDeviceId: true
        }
    })
    const app = getApp()
    app.globalData.nim = nim
    
    const nimPushPlugin = uni.requireNativePlugin('NIMUniPlugin-PluginModule')
    nim.V2NIMSettingService.setOfflinePushConfig(
        plugin: nimPushPlugin,
        {
            miPush: {
                appId: 'xxx',
                appKey: 'yyy',
                certificateName: 'XIAOMI_PUSH_CERT'
            },
            vivoPush: {
                certificateName: 'VIVO_PUSH_CERT'
            },
            oppoPush: {
                appId: 'xxx',
                appKey: 'yyy',
                secret: 'zzz',
                certificateName: 'OPPO_PUSH_CERT'
            },
            hwPush: {
                appId: 'xxx',
                certificateName: 'HUAWEI_PUSH_CERT'
            },
            fcmPush: {
                certificateName: 'FCM_PUSH_CERT'
            },
            mzPush: {
                appId: 'xxx',
                appKey: 'yyy',
                certificateName: 'MEIZU_PUSH_CERT'
            },
            honorPush: {
                certificateName: 'HONOR_PUSH_CERT'
            },
            apns: {
                certificateName: 'APPLE_PUSH_CERT'
            }
        }
    })
    
    await nim.V2NIMLoginService.login(accountId, token)
    
  3. App.vue 中,监听应用是否退至后台,并通过 updateAppBackground 告知云信服务器应用状态。

    当应用退至后台时,Android 应用仍可以收到 IM SDK 的消息,开发者可以根据这些设置应用通知。而 iOS 则无法激活SDK的回调函数。因此,iOS 退至后台时,应该通过下面代码告知云信服务器,然后云信服务器会给处于后台的 iOS 应用发送离线推送。

    onShow: function() {
        const app = getApp()
        app && app.globalData.nim && app.globalData.nim.V2NIMSettingService.setAppBackground(false)
    },
    onHide: function() {
        const app = getApp()
        app && app.globalData.nim && app.globalData.nim.V2NIMSettingService.setAppBackground(true)
    }
    

步骤 4:测试离线推送

消息发送方:

发送消息或自定义系统通知给接收方(离线),具体的收发流程可参见消息收发自定义系统通知收发

这里以发送文本消息为例,通过调用 sendTextMsg 实现。

const message = nim.V2NIMMessageCreator.createTextMessage('hello world')
const res = await nim.V2NIMMessageService.sendMessage(message, 'senderId|1|receiverId')

消息接收方:

登录 IM 账户后,杀死应用,或者 iOS 手机退到后台时,能够接收到推送消息。

相关信息

Sample code

SampleCode 地址

推送相关文档

推送注意事项

华为

  • 华为应用配置的常规页面包含项目应用的 Client ID 和 Client Secret,两者对应的参数不一致,请下拉至页面底部,获取应用的 Client ID 和 Client Secret。
  • 必须添加打包的 SHA256 证书指纹,SHA256 证书指纹需与自己的打包证书一致。
  • 华为注册厂商推送服务时,包含 agconnect-services.json 文件。开发者需下载该文件,并将其放至项目原生插件目录下: nativeplugins/NIMUniPlugin/android/assets/ 文件夹下。
  • 若修改项目、应用信息、开发服务设置,都需要重新下载配置 agconnect-services.json 文件。配置 agconnect-services.json 文件后,需要重新构建自定义基座。
  • 注意云信业务后台配置证书时,需要使用华为应用的clientIdclientKey
  • 未上架的应用一天只能够接收两条推送。
  • 通过透传参数,可以设置消息透传为测试服透传,这样一天能够测试 500 条消息:
jsawait nim.V2NIMMessageService.sendMessage(message, 'senderId|1|receiverId', {
    pushConfig: {
        pushPayload: '{"pushTitle":"bonjour 2","hwField":{"androidConfig":{"target_user_type":1}}}'
    }
})

VIVO

  • 必须在 manifest.json 文件中设置 PUSH_VIVO_APPIDPUSH_VIVO_APPKEY
  • 如果是离线打包,需要在工程的 AndroidManifest.xmlApplication 节点中添加以下代码:
    <meta-data
      android:name="api_key"
      android:value="xxxx" />
    <meta-data
      android:name="app_id"
      android:value="xxxx" />
    
  • vivo 每日推送限制为 5 条消息。

荣耀

必须在 manifest.json 文件中设置 PUSH_HONOR_APPID

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)。
  • 检查是否对会话开启免打扰。若开启,则接收不到推送通知,请先关闭。
  • 检查手机端是否开启应用通知接收权限。若未开启,则接收不到推送通知,请开启。
此文档是否对你有帮助?
有帮助
去反馈
  • 功能概览
  • 前提条件
  • 实现步骤
  • 步骤 1:上传推送证书至云信控制台
  • 步骤 2:设置 uni-app 工程
  • 步骤 3:实现离线推送
  • 步骤 4:测试离线推送
  • 相关信息
  • Sample code
  • 推送相关文档
  • 推送注意事项
  • 华为
  • VIVO
  • 荣耀
  • OPPO
  • FCM
  • iOS
  • 常见问题