小程序音视频通话(for 硬件) 您所在的位置:网站首页 手机的小插件 小程序音视频通话(for 硬件)

小程序音视频通话(for 硬件)

2023-03-13 18:04| 来源: 网络整理| 查看: 265

# 小程序音视频通话(for 硬件)

接入流程和常见问题也可参考微信小程序音视频通话(for 硬件) 使用手册

# 1. 产品介绍

借助微信小程序音视频通话(for 硬件)能力,硬件开发者可以通过小程序硬件框架(WMPF),实现智能设备和手机微信端的一对一音视频通话,满足实时触达场景,提升通话体验。

下图为手机端的示意图,授权弹窗、通话提醒、通话界面为微信提供的统一界面,硬件小程序接入微信 VOIP 通话插件后,可实现上述功能。

适用于校园话机、门禁机、智能门锁、智慧中控屏、智能电视、智能摄像头、智能音箱、智慧养老等多种设备和场景,支持硬件设备和手机端双向通话,实现通话强提醒。

# 2. 接入指引

以下几个环节可以同时进行,涉及到多个平台侧的审核流程,请提前预留时间。

# 2.1 硬件设备要求

这里指与用户微信进行通话的对端设备,并非指运行微信客户端的手机设备。

目前只支持安卓设备,且需要能满足小程序硬件框架运行要求; 具有音视频能力(麦克风、摄像头等硬件设备); 设备的 RPMB (Replay Protected Memory Block) 分区未被使用过。 # 2.2 小程序硬件框架 (WMPF) 接入

注册微信终端合作平台和微信开放平台账号、登记设备信息等环节均涉及平台审核,请提早准备。

参考文档指引,完成「微信终端合作平台 (wecooper)」企业主体账号注册、移动应用绑定和硬件注册的流程。

本步骤主要是将设备接入微信的设备体系,完成设备与 APP,以及 APP 与小程序之间的关联。

为避免混淆,移动应用的 appId 一般被称为 hostAppId; 每一台硬件设备都需要使用 hostAppId 身份调用 addDevice 接口完成注册,才可以使用 WMPF。 # 2.3 设备接入

此环节涉及平台审核,请提早准备。

小程序想要使用音视频通话能力能力,需要接入设备,详见「设备接入」文档。

本步骤主要是将设备接入微信小程序的硬件能力,完成小程序与设备之间的关联。

完成接入后,开发者可获得由平台分配的 model_id 。model_id 对应一种设备类型,也是调用小程序设备能力相关接口的重要凭证。

# 2.4 小程序插件接入

小程序音视频通话的主要功能通过「VOIP 通话」这一小程序插件(appId: wxf830863afde621eb)提供。

登录「小程序管理后台」——「设置」——「第三方设置」——「插件管理」,点击「添加插件」,搜索并添加「VOIP 通话」插件。

# 3. 设备端开发

设备端需要集成 VOIP SDK 进行设备验证所需的 RPMBD 服务。设备厂商需要保证设备的 RPMB 分区没有被使用过。

# 3.1 部署 RPMBD 服务

请在 此处 下载对应平台、版本的 rpmbd 二进制文件(名称为 rmpbd)

小程序音视频通话需要使用 EMMC/UFS 存储上的 RPMB 分区来保证设备的身份。设备厂商需要内置一个 RPMB 分区读写及通信的服务,并保证服务能够开机正常启动。

具体流程可以参考 RPMBD 服务文档

注意:

每一颗 EMMC/UFS 存储芯片的 RPMB KEY 只能被写一次。 如果被写入错误的值 (非注册时的 model_id 和 sn),那么这颗芯片就无法用于 VOIP 通话服务。 # 4. 应用开发(安卓)

在设备端,开发者需要运行一个安卓应用(文档中也称为小程序 Launcher),用来进行设备注册、运行小程序和发起 VOIP 通话。

# 4.1 使用安卓 WMPF 启动小程序

在安卓平台上,小程序视频通话能力是在小程序中实现的。需要由设备端运行的安卓应用拉起开发者开发的小程序来发起和接听音视频通话。

在完成 2.2 中的接入流程,并进行设备注册后,可以获得 WMPF 运行所需的 productId 、keyVersion、deviceId、signature 等硬件信息。

请参考文档中的说明,完成下列操作:

部署 WMPF Service APK; 在应用中集成 WMPF Client; 调用 ActivateDevice 完成设备激活; 调用 LaunchWxaApp 启动指定的小程序。 # 4.2 接入 VOIP SDK 并注册设备

请在 此处 下载 VOIP SDK 的 aar 文件(名称为 voipsdk-x.x-release.aar)。

开发者需要在小程序的 Launcher 应用中接入 VOIP SDK,SDK 主要提供以下能力

注册设备:将 model_id 和 SN 与设备绑定。一旦成功后 SN 不可修改。 获取拨打方票据 (caller_ticket):进行设备验证并从微信后台获取票据,设备端发起通话时传给 VOIP 通话插件的 initByCaller 接口的 voipToken 参数。

在发起通话前,需要先完成设备注册。

具体接口和示例代码请参考 SDK 使用文档。

注意:

此处使用的 SN,必须经过 WMPF 的 addDevice 接口作为 deviceId 注册,并与 WMPF 设备激活时使用的 deviceId 一致。 否则后续无法正常发起通话。 使用 VOIP SDK 时需要保证 rpmbd 服务已经成功运行。 # 5. 小程序开发

开发者需要开发(或使用现有)小程序,接入「VOIP 通话」插件,实现拨打和接听音视频通话的能力。

与安卓设备通话时,开发者需要使用同一个小程序,既运行在安卓设备端(设备发起或接听通话),也运行在手机端微信客户端(手机用户发起或接听通话)。

设备端和用户的手机微信客户端,都既可以作为拨打方(caller),也可以作为接听方(listener)。

# 5.1 接入「VOIP 通话」插件

完成 2.4 中的插件接入后,参考插件文档在小程序中引入插件。

# 5.2 用户授权

设备和用户间如果要进行通话,需要用户在手机端先对设备进行授权。

# 5.1.1 请求授权

用户授权前,需要在小程序中,从开发者的后台通过获取设备票据 接口拿到设备票据 snTicket。

拿到 snTicket 后,需要在小程序内调用 wx.requestDeviceVoIP 请用户进行授权。

需要基础库 >= 2.27.3 支持

wx.requestDeviceVoIP({ sn: 'xxxxxx', // 向用户发起通话的设备 sn,需要与 4.2 中注册设备时一致 snTicket: 'xxxxxx', // 获取的 snTicket modelId: 'xxxxxx', // 2.3 设备接入获取的 model_id deviceName: 'xxx设备', // 设备名称,用于授权时显示给用户看 success(res) { console.log(`requestDeviceVoIP success:`, res) }, fail(err) { console.error(`requestDeviceVoIP fail:`, err) }, })

注意:

授权框中「设备名字」= 「传入 deviceName」 + 「modelId 对应设备型号」。如「devcieName」传入「iot」,modelId 对应设备型号是「测试机」,最终名字为「iot测试机」

开发者需要兼容用户取消授权的情况

用户同意授权后,小程序设置页面中会出现「语音、视频通话提醒」模块,点击进入后用户可以管理已授权的设备,并可以取消授权。(需要微信客户端 >= 8.0.30 支持) 每台设备都需要用户单独进行授权。如果用户拒绝授权或在设置页中取消授权,再次调用requestDeviceVoIP不会出现授权弹框。开发者应引导用户在设置页中手动开启。 在最近使用中删除小程序后,授权记录会被清空。 在发起通话前,建议开发者通过 5.2.2 和 5.2.3 所述方式检查授权状态。并在必要时提醒用户重新授权。 # 5.2.2 查询授权设备列表

查询当前登录的用户同意/拒绝授权了哪些设备。在手机端调用,可用于在手机端发起通话前验证授权状态。

基础库 >= 2.30.3 支持

// 小程序基础库接口 wx.getDeviceVoIPList({ success(res) { console.log('[getDeviceVoIPList]:', res.list) // [{sn: 'xxx', model_id: 'xxx', status: 0}] } }) 属性 类型 说明 errcode number 错误码 errmsg string 错误信息 list Info[] sn 授权信息,status: 1表示已授权,0表示未授权# 5.2.3 查询 openId 是否授权设备

根据 openId,查询指定用户是否授权某台设备。一般在设备端使用,可用于在设备端发起通话前(联系人页面)验证授权状态。

const wmpfVoip = requirePlugin('wmpf-voip').default // VOIP 插件接口 wmpfVoip.getIotBindContactList({ sn: "设备sn", model_id: "申请的modelid", openid_list: ["openid_1", "openid_2"], // 传入需要验证的openid列表 }) 属性 类型 说明 errcode number 错误码 errmsg string 错误信息 contact_list Info[] openid授权信息,status: 1表示已授权,0表示未授权# 5.3 设备拨打手机微信

在用户对设备进行授权(参见 5.2)后,设备可以向已授权用户发起音视频通话。

如果要获取通话过程的各类事件,可以使用插件的 onVoipEvent 接口。详情请参考插件文档

# 5.3.1 安卓设备端发起通话

发起通话前,一般需要用户选择拨打给的用户和通话的类型(音频/视频)。

根据业务场景不同,发起通话前的流程(如选择联系人和房间类型)可以在小程序的另一个页面中或者安卓应用中进行。

# 由小程序页面进入通话页面

适用于用户发起通话前的页面(如联系人选择等)是小程序页面时。

发起通话时,设备端需要在之前的页面中调用插件的 initByCaller 接口获取 groupId,然后跳转到插件的发起通话页面。

const wmpfVoip = requirePlugin('wmpf-voip').default // 获取 groupId const roomType = 'video' const { groupId, isSuccess } = await wmpfVoip.initByCaller({ caller: { id: 'sn', // 设备 SN // 不支持传 name,显示的是授权时「deviceName」+「modelId 对应设备型号」 }, listener: { // 参见 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 获取 id: 'openId' // 接听方 用户 openId name: 'xxxxxx', // 接听方名字,仅显示用 }, roomType, // 房间类型。voice: 音频房间;video: 音视频房间 businessType: 1, // 1 为设备拨打手机微信 voipToken: 'xxxxxxxxxx', // 4.2 中从 voip SDK 获取的 caller_ticket miniprogramState: 'formal', // 开发调试时建议使用 developer }) if (isSuccess) { // 跳转到插件的通话页面 const callPagePlugin = 'plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin' wx.redirectTo({ url: `${callPagePlugin}?isCaller=1&roomType=${roomType}&groupId=${groupId}`, }) } else { wx.showToast({ title: '播打失败', icon: 'error', }) } # 由安卓应用直接进入通话页面

适用于用户发起通话前的页面(如联系人选择等)是安卓应用页面时。

发起通话时,需要安卓应用调用 WMPF LaunchWxaApp 接口拉起小程序,path 直接使用插件的拨打页面 plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin?isCaller=1&roomType=${roomType},roomType 按用户实际选择填写。路径后可以带自定义参数,如 &a=1

这种情况下,开发者可以直接在小程序 App.onShow 或插件 callPageOnShow 事件回调时调用 initByCaller,插件会直接进入拨打状态,不需要额外进行页面跳转。

建议开发者使用 5.5.2 的「小程序预热」能力加快小程序的启动速度。

const wmpfVoip = requirePlugin('wmpf-voip').default App({ onShow() { const { query } = wmpfVoip.getPluginEnterOptions() if (query.isPreLaunch) { // 小程序预热场景,无需处理 } else if (query.isCaller === '1') { // 发起通话场景 if (!query.groupId) { // 安卓应用直接进入通话页面 wmpfVoip.initByCaller({/* 参数省略,请参考前一小节 */}) .catch((e) => { wx.showToast({ title: '播打失败', icon: 'error', }) }) } else { // 已经获取到 groupId 小程序页面跳转进入,可以不处理 } } else { // 接听通话场景 } } })

注意

设备端发起通话时必须处于未登录状态(如果扫码登录过 WMPF,需先退出登录)。 否则会返回 errCode: 18。 给用户推送的接听提醒会在调用 initByCaller 后由微信后台直接下发,不需要开发者额外调用服务端下发消息的接口。 caller_ticket 和 roomType 可以通过拉起小程序的 path 中的 query 传递给小程序。 设备上,APP 拉起小程序或发起通话较慢时,请参考 5.5 的建议进行优化。 initByCaller 支持的其他参数,请参见插件文档 # 5.3.2 手机端接听通话

用户在手机端可以收到「响铃+振动」的强提醒通知,点击接听按钮后,会启动小程序并直接进入「VOIP 通话」插件页面接听通话。完成通话后,会跳转到开发者配置的页面。

开发者可以自定义接听页面按钮,以及通话结束跳转页。详情请参考插件文档

# 5.4 手机微信拨打设备

在用户对设备进行授权(参见 5.2)后,可以向设备发起音视频通话。

此时,设备端会收到一条 WMPF 的推送消息,开发者需要在收到消息后拉起小程序的指定页面让用户接听通话。

如果要获取通话过程的各类事件,可以使用插件的 onVoipEvent 接口。详情请参考插件文档

# 5.4.1 手机端发起通话

发起通话前,一般需要用户在小程序中选择拨打的设备和通话的类型(音频/视频)。

发起通话时,开发者需要先从后台拿到从设备端获取的 pushToken,并在小程序中调用插件的 initByCaller 接口获取 groupId,然后跳转到插件的发起通话页面。

const wmpfVoip = requirePlugin('wmpf-voip').default // 获取 groupId const roomType = 'video' const { groupId, isSuccess } = await wmpfVoip.initByCaller({ caller: { // 参见 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 获取 id: 'openId', // 拨打方用户 openId name: 'xxxxxx', // 拨打方名字,仅显示用 }, listener: { id: 'sn' // 设备 SN }, roomType, // 房间类型。voice: 音频房间;video: 音视频房间 businessType: 2, // 2 为手机微信拨打设备 voipToken: 'xxxxxxxxxx', // 从设备获取的 pushToken miniprogramState: 'formal', // 开发调试时建议使用 developer }) if (isSuccess) { // 跳转到插件的通话页面 const callPagePlugin = 'plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin' wx.redirectTo({ url: `${callPagePlugin}?isCaller=1&roomType=${roomType}&groupId=${groupId}`, }) } else { wx.showToast({ title: '播打失败', icon: 'error', }) }

注意

建议开发者在服务端维护 sn 与 pushToken 的关联,提前在设备端获取 pushToken并存到后台,并在 pushToken 过期前进行刷新。 initByCaller 支持的其他参数,请参见插件文档。 发起通话时,需要保证设备已激活并联网在线。 给设备推送的消息会在调用 initByCaller 后由微信后台直接下发,不需要开发者额外调用服务端下发消息的接口。 # 5.4.2 安卓设备端接听通话

在手机端发起通话后,设备端会收到一条 WMPF 的推送消息。开发者应该进行以下处理:

1) 绑定消息监听

开发者需要在 WMPF 中调用 SetPushMsgCallback 注册消息监听。注意,这一步必须在通话发起前进行。

2) 展示来电通知/提醒(可选)

收到消息后,开发者可以根据产品需要展示来电通知(样式可以自定义),也可直接拉起小程序让用户进行接听。

3) 打开小程序接听

推送消息为 JSON 字符串,解析后格式如下

{ "path": "plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin?roomType=roomType&groupId=groupId&listenerId=设备sn&callerName=拨打方名称&customQuery字符串", // 小程序启动路径 "appType": 0, // 0: 正式版 1: 开发版 2: 体验版 "appid": "wx********", // 小程序appid }

开发者需要使用上述参数,调用 WMPF LaunchWxaApp 接口打开小程序的接听界面。

注意

如果开发者在收到消息后展示了自定义的来电通知,可以在启动小程序的 path 后添加 &isClickedHangOnBtn=1。此时用户进入小程序就会直接接听通话,不需要再次点击插件通话页面「接听」按钮。 建议在安卓 APP 中使用 IPCInvoker.addRemoteProcDiedListener(WMPFService.WMPF_SERVICE_PROCESS_NAME, listener) 监听 WMPF 退出事件,并重新启动并激活 WMPF,以防止 WMPF 异常退出后消息丢失。 设备上,APP 拉起小程序或接听通话较慢时,请参考 5.5 的建议进行优化。 # 5.5 性能与体验优化

要让用户的接听和拨打体验更加流畅,关键是要缩短接听和拨打时小程序启动和一些网络请求的耗时。

小程序的冷启动需要一定的时间,尤其是在性能较差的设备上,启动耗时可能会偏长。影响用户拨打和接听音视频通话的体验。

# 5.5.1 小程序侧启动性能优化

建议开发者参考《启动性能优化文档》优化小程序的启动耗时。

# 5.5.2 安卓 WMPF 小程序预热(建议)

在设备端 WMPF,我们额外提供了「小程序预热」的能力,在用户使用小程序前,就预先将小程序在后台以无界面的形式启动并常驻运行,以便用户使用时可以直接把小程序切前台,而不需要完整进行冷启动流程。流程如下:

WMPF 激活后,在用户使用小程序之前,可以调用LaunchWxaApp提前运行小程序。 isForPreWarmLaunch 参数需要传 true,才会实现后台启动的效果,否则小程序会被拉到前台。 通常情况下,建议指定 path 为插件的拨打/接听页面 plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin?isPreLaunch=1。如果开发者需要小程序启动时打开其他页面(例如联系人列表页),也可以指定预热其他页面。 设备端发起或接听通话,真正需要使用小程序时,再调用LaunchWxaApp传入正常的带有 query 的 path 等启动参数,即可复用之前预热的环境,把小程序拉到前台。 预热和正式使用时传入的 path 参数的路径部分需保持一致,query 部分可不同。否则会额外触发一次页面的 reLaunch

小程序开发者需要对预热启动的情况进行识别和适配:

建议开发者在预热路径中增加一个 isPreLaunch=1 参数(也可以使用其他名称),标识预热进入的情况 在 App.onShow 事件的 query 中,需要判断有无 isPreLaunch。isPreLaunch 为 1 时,可以认为是预热启动,不应发起通话。 无 isPreLaunch 是正常启动,可以使用从 wmpfVoip.getPluginEnterOptions() 拿到的参数调用 initByCaller。 const wmpfVoip = requirePlugin('wmpf-voip').default App({ onShow() { const options = wmpfVoip.getPluginEnterOptions() if (options.query.isPreLaunch) { // 小程序预热场景,无需处理 } else { // 正常启动场景,执行其他业务逻辑 } } })

注意

参考 5.5.4,如果关闭小程序时未指定 keepRunning 参数为 true,则小程序关闭后需要重新进行预热。 # 5.5.3 安卓 WMPF 小程序环境预加载

如果做了小程序预热,无需再进行环境预加载

如果因为设备资源紧张等原因,不便通过预热的方式将小程序后台常驻,也可以使用 PreloadRuntime 接口对小程序环境进行预加载。这个接口只会预创建一个基础的小程序运行环境和小程序基础库,不会启动某个具体的小程序。

# 5.5.4 安卓 WMPF 关闭小程序时切后台

默认情况下,调用 WMPF CloseWxaApp 接口关闭小程序时,会直接销毁小程序的实例,下次使用需要重新冷启动(或预热)。

建议开发者在关闭小程序时,传入 keepRunning 为 true,此时小程序会直接切后台,下次使用时可以直接复用,避免重复冷启动或重复预热。

# 5.5.5 票据预获取

调用插件 initByCaller 发起通话时使用的 caller_ticket 和 pushToken 这类票据都需要从微信后台获取,如果在用户点击后再获取,可能会延长发起通话的耗时。

建议开发者在用户发起通话的前置页面(例如:联系人页面等)提前准备好这些参数,如果用户在票据有效期内发起通话,不需要重新获取。

# 5.6 关于调试 # 5.6.1 使用开发版小程序

接听方收到消息推送点击接听后,默认打开的是正式版的小程序。

在开发阶段,建议在调用 wmpfVoip.initByCaller 时额外传入 miniprogramState 参数指定打开开发版小程序。

const result = await wmpfVoip.initByCaller({ // 其他参数省略 miniprogramState: 'developer', // formal/正式版(默认);trial/体验版;developer/开发版 })

注意:

接听方应提前扫微信开发者工具生成的开发版二维码下载开发版。 正式上线时应注意切换为正式版,可以使用 wx.getAccountInfoSync 接口判断当前的小程序版本。 # 5.6.2 安卓 WMPF 退出登录态后如何使用开发版/体验版

设备端发起通话时必须处于未登录状态。需要提前在有登录态的情况提前启动过开发版小程序完成代码包下载,再退出登录。步骤如下

开发者在开发者工具点击「预览」,将开发版小程序代码包上传到后台。也可提交成体验版; 在 WMPF 上由同个开发者扫码登录; 在 WMPF 上启动开发版或体验版小程序,此时小程序代码包已被下载到本地。如果通话页面位于分包,也要访问下分包页面; 在 WMPF 上退出登录; 重新打开小程序,会使用本地代码包启动。此时可以调用 initByCaller 发起通话。 # 6. 常见问题

1) WMPF 获取不到正确的摄像头,或摄像头画面旋转

可以使用 InitGlobalConfig 接口指定小程序使用的摄像头三元组(productId、vendorId、serialNumber),也可以指定摄像头画面的旋转角度。

fun initGlobalConfig() { val jsonConfig = JSONObject() try { //三元组匹配摄像头 jsonConfig.put("usbCameraProductId", 0) jsonConfig.put("usbCameraVendorId", 0) jsonConfig.put("usbSerialNumber", "") // 如果 wmpf 预览画面方向不对,根据实际情况调整角度 jsonConfig.put("usbCameraRotationAngle", 180) // 系统摄像头需使用 cameraRotationAngle // 如果推流方向不对(即微信侧视频方向不对),调整 true / false jsonConfig.put("usbCameraPushFlip", false) // 系统摄像头需使用 cameraPushFlip val json = jsonConfig.toString() LogUtils.d(TAG, "initGlobalConfig", json) Api.initGlobalConfig(json) .subscribe({ LogUtils.d(TAG, GsonUtils.toJson(it)) warmLaunch() }, { LogUtils.d(TAG, GsonUtils.toJson(it)) warmLaunch() }) } catch (e: Exception) { } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有