VenusSDK接入与开发指南(Android)vX.X.X =====================================
# 1. 文档概述 本文介绍在 Android 平台上集成 VenusSDK 的方法,实现应用与 VenusOS 智能眼镜的连接与交互,包括设备连接、设备信息获取、设备状态同步、系统设置、固件升级、以及各项功能(实时语音转文字服务、导航、提词)的信息同步。
# 2. 支持平台与版本 - Android 7.0 及以上 - minSdk 24 及以上 - 支持 Classic Bluetooth 连接
# 3. 快速开始
## 3.1 集成SDK 1. 将 `VenusSDK_vx.x.x_release.aar` 复制到 Application Module/libs 文件夹 2. 在 app 的 build.gradle.kts 中添加依赖: ```gradle dependencies { implementation(files("libs/VenusSDK_vx.x.x_release.aar")) } ```
## 3.2 声明权限 根据场景需要,在 `/app/src/main/AndroidManifest.xml` 文件中申请获取相应的设备权限: ```xml ```
## 3.3 混淆配置 在 `app/proguard-rules.pro` 文件中添加: ```proguard -keep class com.jueyuantech.venussdk.** { *; } -dontwarn com.jueyuantech.venussdk.** ```
## 3.4 SDK初始化 VenusSDK 主要提供:`VNSDK`、`VNCommon` 和 `VNOTA` 接口: - `VNSDK` 负责 SDK 初始化、自定义参数、获取版本构建信息等; - `VNCommon` 负责处理与设备相关的常用功能,如设备连接管理、系统配置、状态监听和功能调用等; - `VNOTA` 负责固件升级相关功能。
在 Application 类中初始化 SDK: ```java VNSDK.init(this, new VNOptions()); ```
> 📝 **注意:** 调用 `VNSDK.init` 后,SDK 内部同时会对 VNCommon 和 VNOTA 进行初始化,开发者无需手动初始化,可直接调用其功能。
## 3.5 获取SDK构建信息 获取SDK的版本构建信息: ```java VNVersionInfo versionInfo = VNSDK.getVersionInfo(); ``` 返回的 `VNVersionInfo` 对象包含以下信息: - buildType:构建类型 - code:版本号 - name:版本名称 - commit:构建提交号 - date:构建日期
# 4. 设备连接和配置
## 4.1 设备扫描 SDK 中不提供扫描设备的接口,开发者需自行扫描附近 **Classic Bluetooth** 蓝牙设备,将获取到的 `BluetoothDevice` 对象传递给 SDK 进行初始化和连接。
## 4.2 设备连接管理 > ℹ️ **提示:** 设备连接是指 APP 与眼镜设备的**业务通路**连接。如有用到**音频通路**连接(A2DP、HFP),开发者需通过Android标准API自行维护。
1. 初始化设备: ```java VNCommon.initDevice(bluetoothDevice); ```
2. 设置连接状态监听: ```java VNCommon.setDeviceServiceListener(new VNDeviceServiceListener() { @Override public void onStateChanged(int state) { // 根据state判断连接状态 switch (state) { case VNConstant.ServiceState.CONNECT_SUCCESS: // 连接成功 break; case VNConstant.ServiceState.CONNECT_ERROR: // 连接失败 break; } } }); ```
3. 连接设备: ```java VNCommon.connect(bluetoothDevice); ```
4. 获取当前连接状态: ```java boolean connected = VNCommon.isConnected(); ```
5. 断开连接: ```java VNCommon.disconnect(); ```
## 4.3 设备信息获取 通过`getDeviceInfo`方法获取设备的基本信息,包括设备名称、MAC地址、固件版本等信息: ```java VNCommon.getDeviceInfo(new VNDeviceInfoCallBack() { @Override public void onSuccess(VNDeviceInfo deviceInfo) { // 获取设备信息成功 // 厂商 String manufacturer = deviceInfo.getManufacturer(); // 型号 String model = deviceInfo.getModel(); // 发行版 String edition = deviceInfo.getEdition(); // 蓝牙MAC地址 String mac = deviceInfo.getMac(); // 设备序列号 String sn = deviceInfo.getSn(); // 固件版本 String firmware = deviceInfo.getFirmware(); // 协议栈版本 String bth = deviceInfo.getBth(); } @Override public void onTimeOut() { // 获取设备信息超时 } @Override public void onFailed() { // 获取设备信息失败 } }); ```
## 4.4 系统配置获取 通过`getSystemConfig`方法获取当前系统的各项配置信息,包括亮度、自动亮度调节、字体大小、系统语言、佩戴检测、触控板等状态: ```java VNCommon.getSystemConfig(new VNSystemConfigCallBack() { @Override public void onSuccess(VNSystemConfig systemConfig) { // 获取系统配置成功 // 屏幕亮度值(0 - 255) Integer brightness = systemConfig.getBrightness(); // 自动亮度调节状态(0 - 关闭,1 - 开启) Integer autoBrightness = systemConfig.getAutoBrightnessEnabled(); // 系统语言 String language = systemConfig.getLanguage(); // 触控板状态(0 - 关闭,1 - 开启) Integer touchpadEnabled = systemConfig.getTouchpadEnabled(); // ...... } @Override public void onTimeOut() { // 获取系统配置超时 } @Override public void onFailed() { // 获取系统配置失败 } }); ```
## 4.5 时间设置 > ℹ️ **提示:** 设备系统时间由 SDK 在设备连接成功时自动设置,正常情况下无需开发者进行设置。 在检测到应用终端时间发生改变的情况下,需开发者主动调用以同步时间: ```java /** * @param timeConfig 时间配置:时间、格式等 */ void setTimeConfig(TimeConfig timeConfig, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例: TimeConfig timeConfig = new TimeConfig(); timeConfig.setTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); VNCommon.setTimeConfig(timeConfig, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` > 📝 **注意:** 若APP时间与眼镜设备系统时间不一致,以下功能会受影响: > - [显示通知](#CUSTOM_54_1)
历史固件版本设置时间方法: ```java /** * @param time 时间戳,单位:秒 * @deprecated prefer setTimeConfig */ void setTime(long time, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例: VNCommon.setTime(System.currentTimeMillis() / 1000, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 4.6 亮度设置 手动设置亮度: ```java /** * @param brightness 0 - 255 */ void setBrightness(int brightness, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:设置亮度值为 128 VNCommon.setBrightness(128, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
自动亮度调节开关: ```java /** * @param enabled * VNConstant.EnableState.ENABLED - 开启 * VNConstant.EnableState.DISABLED - 关闭 */ void setAutoBrightnessEnabled(int enabled, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:开启自动亮度功能 VNCommon.setAutoBrightnessEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` > 📝 **注意:** >- 亮度建议值 80 - 180 之间,结合实际场景调优。 >- 自动亮度功能需设备硬件支持。当自动亮度开启时,手动设置亮度值会被覆盖。
## 4.7 音量设置 眼镜设备音量跟随系统音量设置。
## 4.8 显示模式设置 支持显示模式设置,如全屏显示、半屏显示: ```java /** * @param displayConfig 显示配置:显示模式、显示区域等配置。 */ void setDisplayConfig(DisplayConfig displayConfig, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例: DisplayConfig config = new DisplayConfig(); config.setMode(1); // 显示模式:1 - 全屏,0 - 半屏 VNCommon.setDisplayConfig(config, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 4.9 系统语言设置 系统界面语言设置: ```java /** * @param language BCP 47 语言代码 */ void setLanguage(String language, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:设置系统语言为中文 VNCommon.setLanguage("zh-CN", new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
支持语言列表如下: |语言 |标识符 | |--------------------|------------| | 中文(简体) | zh-CN | | 中文(繁体) | zh-TW | | English | en-US | | 日本語 | ja | | 한국어 | ko | | Deutsch | de | | Français | fr-FR | | Русский | ru | | Italiano | it | | Português (Brasil) | pt-BR | | Español (Spain) | es-ES | | Tiếng Việt | vi | | ภาษาไทย | th | > 📝 **注意:** 支持的语言列表,根据设备固件版本的字库调整。
## 4.10 通知功能设置 设备支持在界面显示通知信息,当功能开启后,用户可以通过 [5.4 通知](#54-通知) 或 ANCS(苹果通知中心服务)向设备发送通知信息。 设置通知功能的开关状态: ```java /** * @param enabled * VNConstant.EnableState.ENABLED - 开启 * VNConstant.EnableState.DISABLED - 关闭 */ void setNotificationEnabled(int enabled, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:开启通知功能 VNCommon.setNotificationEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` > 📝 **注意:** [5.4 通知](#54-通知) 中的**系统通知**不受该设置影响。
## 4.11 触控板设置 用户可以通过眼镜设备的触控区域进行单击、双击、长按、滑动等手势与设备交互。 设置触控板功能的开关状态: ```java /** * @param enabled * VNConstant.EnableState.ENABLED - 开启 * VNConstant.EnableState.DISABLED - 关闭 */ void setTouchpadEnabled(int enabled, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:开启触控板 VNCommon.setTouchpadEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` **使用场景:** - 菜单导航:快速浏览和切换不同功能界面 - 内容控制:确认选择、返回上级等操作 - 特殊场景:在不方便使用语音控制时提供替代操作方式 > 📝 **注意:** 此功能需设备硬件支持。
## 4.12 静置状态自动熄屏设置 通过设备的静置传感器检测设备是否处于静置状态(如放置在桌面)。当检测到设备静置超过 10 秒时,系统自动熄屏。 设置静置熄屏功能的开关状态: ```java /** * @param enabled * VNConstant.EnableState.ENABLED - 开启 * VNConstant.EnableState.DISABLED - 关闭 */ void setIdleDetectionEnabled(int enabled, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:开启功能 VNCommon.setIdleDetectionEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` **使用场景:** - 自动熄屏:用户将设备放置不动时自动进入熄屏模式 - 节能管理:通过自动熄屏机制延长设备使用时间 > 📝 **注意:** > - 此功能需设备硬件支持。 > - 在任意功能界面进入熄屏后,30 秒会收到 [系统状态监听](#CUSTOM_51_1) 的`onViewChanged(int vnAppId)`退回`HOME`主界面的消息。
## 4.13 非活跃状态自动熄屏设置 非活跃状态监听,是指设备监听超过一段时间(timeout)无新消息抵达设备,与设备无消息交互,则设备自动熄屏。 ```java /** * @param timeout 单位:秒,0 表示关闭 */ void setInactivityTimeout(int timeout, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:设置无交互 1 分钟后自动熄屏 VNCommon.setInactivityTimeout(60, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` > 📝 **注意:** > - 在任意功能界面进入熄屏后,30 秒会收到 [系统状态监听](#CUSTOM_51_1) 的`onViewChanged(int vnAppId)`退回`HOME`主界面的消息。 > - 在特殊场景(如提词)需要保持亮屏时,可周期性(间隔低于 timeout)调用 `VNCommon.sendKeepAlive()` 发送保活信号。
## 4.14 熄屏状态自动关机设置 设备支持熄屏一段时间(timeout)后自动关机设置: ```java /** * @param timeout 单位:秒,0 表示关闭 */ void setPoweroffTimeout(int timeout, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:设置熄屏 5 分钟后自动关机 VNCommon.setPoweroffTimeout(300, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 4.15 佩戴检测设置 开启佩戴检测后,当用户戴上设备时自动亮屏,摘下设备时自动熄屏: ```java /** * @param enabled * VNConstant.EnableState.ENABLED - 开启 * VNConstant.EnableState.DISABLED - 关闭 */ void setWearDetectionEnabled(int enabled, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例: VNCommon.setWearDetectionEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` > 📝 **注意:** 此功能需设备硬件支持。
# 5 系统状态和操控 用户可以实时获取系统当前的各种状态、事件,结合业务场景来设计实现各项交互: - `运行状态`:熄屏、亮屏 - `充电状态`:正在充电、未在充电 - `电池电量` - `应用的进入和退出` - `触控事件`:长按、双击、前滑、后滑 - `系统主动上报消息`:语音业务请求等
## 5.1 获取、监听、设置系统状态 1. 系统状态监听 通过`setDeviceStatusListener`方法设置设备状态监听器,可以监听设备的系统状态、充电状态、电池电量、应用切换等变化,以及触控板按键事件: ```java // 设置设备状态监听 VNCommon.setDeviceStatusListener(new VNDeviceStatusListener() { @Override public void onSysStateChanged(int sysState) { // 系统状态变化回调 switch (sysState) { case VNConstant.SysState.SCREEN_OFF: // 熄屏状态 break; case VNConstant.SysState.SCREEN_ON: // 亮屏状态 break; } } @Override public void onChargeStateChanged(int chargeState) { // 充电状态变化回调 switch (chargeState) { case VNConstant.ChargeState.NOT_CHARGING: // 未充电 break; case VNConstant.ChargeState.CHARGING: // 充电中 break; } } @Override public void onBatteryChanged(int battery) { // 电池电量变化回调(0-100) } @Override public void onViewChanged(int vnAppId) { // 视图状态变化回调 switch (vnAppId) { case VNConstant.View.HOME: // 主页 break; case VNConstant.View.TRANSCRIBE: // 转写页 break; case VNConstant.View.TRANSLATE: // 翻译页 break; case VNConstant.View.MAP: // 地图页 break; case VNConstant.View.PROMPTER: // 提词器页 break; case VNConstant.View.READER: // 阅读页 break; } } @Override public void onTouchEvent(int event) { // 设备触控板事件回调,在设备端未消费的事件 switch (event) { case VNConstant.TouchEvent.SINGLE_TAP: // 单击 break; case VNConstant.TouchEvent.DOUBLE_TAP: // 双击 break; case VNConstant.TouchEvent.LONG_PRESS: // 长按 break; case VNConstant.TouchEvent.SLIP_LEFT: // 前滑 break; case VNConstant.TouchEvent.SLIP_RIGHT: // 后滑 break; default: } } }); ```
2. 通过`getSystemStatus`方法**主动获取**设备当时的运行状态,包括系统状态、充电状态、电池电量等: ```java VNCommon.getSystemStatus(new VNSystemStatusCallBack() { @Override public void onSuccess(int sysState, int chargeState, int battery) { // 获取设备状态成功 // sysState: 系统状态,参考 VNConstant.SysState // chargeState: 充电状态,参考 VNConstant.ChargeState // battery: 电池电量(0-100) } @Override public void onFail(int code, String msg) { // 获取设备状态失败 } }); ```
3. 在特殊场景下,开发者可**主动设置**系统运行状态: ```java /** * @param sysState * VNConstant.SysState.SCREEN_ON - 亮屏状态 * VNConstant.SysState.SCREEN_OFF - 熄屏状态 */ void setSysState(int sysState, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:将设备熄屏 VNCommon.setSysState(VNConstant.SysState.SCREEN_OFF, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); // 示例:将设备亮屏 VNCommon.setSysState(VNConstant.SysState.SCREEN_ON, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.2 触控板 开发者可通过 [系统状态监听](#CUSTOM_51_1) 中的 `onTouchEvent(int event)` 回调方法监听到未被设备消费的触摸事件。 在特殊场景下,支持开发者主动发送触摸事件: ```java /** * @param event * VNConstant.TouchEvent.SINGLE_TAP: 单击事件 * VNConstant.TouchEvent.DOUBLE_TAP: 双击事件 * VNConstant.TouchEvent.LONG_PRESS: 长按事件 * VNConstant.TouchEvent.SLIP_LEFT: 向左滑动事件 * VNConstant.TouchEvent.SLIP_RIGHT: 向右滑动事件 */ void sendTouchEvent(int event) ``` ```java // 示例:发送长按事件 VNCommon.sendTouchEvent(VNConstant.TouchEvent.LONG_PRESS); ```
## 5.3 应用的进入和退出 当系统被触控板或其他途径操控进入和退出应用时,开发者通过 [系统状态监听](#CUSTOM_51_1) 中的 `onViewChanged(int vnAppId)` 回调方法监听到相应的请求。 也可以主动进行应用跳转: ```java /** * @param vnAppId * VNConstant.View.HOME - 主页 * VNConstant.View.TRANSCRIBE - 语音转写 * VNConstant.View.TRANSLATE - 翻译 * VNConstant.View.MAP - 导航 * VNConstant.View.PROMPTER - 题词 * VNConstant.View.GALLERY - 图库 * VNConstant.View.AI - AI会话 */ void setView(int vnAppId, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:进入翻译应用界面 VNCommon.setView(VNConstant.View.TRANSLATE, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); // 示例:返回主页 VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
获取设备当前所在应用: ```java void getView(VNViewCallBack vnViewCallBack) ``` ```java // 示例:获取设备当前所在应用 VNCommon.getView(new VNViewCallBack() { @Override public void onSuccess(int vnAppId) { // vnAppId 参考 VNConstant.View } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.4 通知 系统支持在界面上方与用户进行通知交互: 1. 显示通知: ```java /** * @param vnNotificationInfo * (必选)id - 区分通知用于更新、移除 * (必选)title - 标题 * (必选)msg - 内容 * (必选)type - 通知类型:0-用户,1-系统 * (必选)duration - 持续时间,单位:秒;0 - 常驻等待关闭,n - 时间到自动关闭 * (必选)timeConfig - 通知时间 */ void addNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack) ``` 参数说明: - 类型 `type`: - `0 - 用户`:当 [4.10 通知功能设置](#410-通知功能设置) 关闭时,用户通知将被过滤不显示; - `1 - 系统`:不受 [4.10 通知功能设置](#410-通知功能设置) 状态影响 - 持续时间 `duration`: - `0 - 常驻等待关闭`:显示后需调用 [移除通知](#CUSTOM_54_2) 关闭,或通过双击触控板关闭 - `n - 时间到自动关闭`:n 秒时间到后自动关闭 ```java // 示例:显示通知: VNNotificationInfo notificationInfo = new VNNotificationInfo(); notificationInfo.setId(1000); notificationInfo.setTitle("通知标题"); notificationInfo.setMsg("通知内容"); notificationInfo.setType(0); notificationInfo.setDuration(3); TimeConfig timeConfig = new TimeConfig(); timeConfig.setTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); notificationInfo.setTimeConfig(timeConfig); Bitmap appIcon = ...; // (可选)通知图标 String iconBmpData = VNCommon.getVenusBmpRawData(appIcon, 32, 32, true); notificationInfo.setIconBitmap(iconBmpData); VNCommon.addNotification(notificationInfo, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
2. 更新通知: ```java /** * @param vnNotificationInfo * (必选)id - 区分通知用于更新、移除 * (可选)msg - 内容 */ void updateNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:更新已有通知的内容 notificationInfo.setId(1000); notificationInfo.setMsg("更新后的通知内容"); VNCommon.updateNotification(notificationInfo, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
3. 移除通知: ```java /** * @param vnNotificationInfo * (必选)id - 区分通知用于更新、移除 */ void removeNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:移除指定ID的通知 notificationInfo.setId(1000); VNCommon.removeNotification(notificationInfo, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.5 文件系统 系统支持用户在 [提词信息同步](#65-提词信息同步)、 [图库](#66-图库)等应用场景下,对设备文件进行管理。如查看设备上当前已上传的提词文件列表、上传新文件等等操作。
1. 文件描述 `VNFile`用于描述设备中的文件信息,包括文件名,文件/文件夹,大小等描述。 部分 API 接收 `VNFile` 参数时,开发者可通过接口将 `File` 转为 `VNFile`: ```java /** * @param file 原文件 * @param vnFileType 应用场景 * VNConstant.VNFile.Type.PROMPTER - 题词 * VNConstant.VNFile.Type.GALLERY - 图库 * @return VNFile 设备文件描述 */ VNFile initVNFile(File file, int vnFileType) ``` ```java // 示例:将本地文件转为题词文件描述 File file = new File("/xxx/xxx.txt"); VNFile vnFile = initVNFile(file, VNConstant.VNFile.Type.GALLERY); ```
2. 文件列表 ```java /** * @param vnFileType 应用场景 * VNConstant.VNFile.Type.PROMPTER - 题词 * VNConstant.VNFile.Type.GALLERY - 图库 */ void getFileList(int vnFileType, VNFileListCallBack vnFileListCallBack) ``` ```java // 示例:获取设备端题词场景文件列表 VNCommon.getFileList(VNConstant.VNFile.Type.PROMPTER, new VNFileListCallBack() { @Override public void onSuccess(List files) { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
3. 上传文件 上传本地文件至设备指定应用场景中: ```java // 示例:上传本地txt文件至设备题词场景中 IVNFileUploadTask vnFileUploadTask = VNCommon.createFileTransferTask(); // 将要上传的本地文件 File file = new File("/xxx/xxx.txt"); // 初始化上传任务,并注册上传回调 vnFileUploadTask.init(file, VNConstant.VNFile.Type.PROMPTER, new VNFileUploadListener() { @Override public void onError(int code, String msg) { // 发生错误,可以通过retry重试并续传 } @Override public void onComplete() { // 上传完成 } @Override public void onProgress(int cur, int total) { // 上传进度 } }); // 开始上传 vnFileUploadTask.start(); // 重试:上传发生错误时通过retry重试并续传 vnFileUploadTask.retry(); // 取消当前正在进行中的任务 vnFileUploadTask.cancel(); ```
4. 删除文件 ```java /** * @param vnFile 设备文件描述 * @param vnCommonCallBack 执行结果回调 */ VNCommon.removeFile(VNFile vnFile, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:删除由getFileList获取到的设备文件列表中的某文件 VNCommon.removeFile(vnFile, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
5. 清空目录 ```java /** * @param vnFileType 应用场景 * VNConstant.VNFile.Type.PROMPTER - 题词 * VNConstant.VNFile.Type.GALLERY - 图库 * @param vnCommonCallBack 执行结果回调 */ void clearFolder(int vnFileType, VNCommonCallBack vnCommonCallBack) ``` ```java // 示例:清空题词文件目录 VNCommon.clearFolder(VNConstant.VNFile.Type.PROMPTER, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
6. 检查本地文件是否在设备存在 通常情况下,如果本地目标文件在设备端已经存在,则不需要重新上传。判断是否存在: ```java /** * @param file 原文件 * @param vnFileType 应用场景 * VNConstant.VNFile.Type.PROMPTER - 题词 * VNConstant.VNFile.Type.GALLERY - 图库 * @param vnCommonCallBack 执行结果回调 */ void isFileExist(File file, int vnFileType, VNCommonCallBack vnCommonCallBack) ``` ```java VNCommon.isFileExist(file, VNConstant.VNFile.Type.GALLERY, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.6 查看存储空间 ```java /** * @param vnRomUsageCallBack 查询结果回调 */ void getRomUsage(VNRomUsageCallBack vnRomUsageCallBack) ``` ```java // 示例:查询设备存储空间情况 VNCommon.getRomUsage(new VNRomUsageCallBack() { @Override public void onSuccess(VNRomUsage usage) { long remaining = usage.getRemaining(); // 单位:KB long total = usage.getTotal(); // 单位:KB } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.7 监听设备主动消息 监听由眼镜设备主动上报的请求,如唤醒、助手等业务: ```java // 示例:设置设备主动上报监听 VNCommon.setDeviceUnsolicitedListener(new VNDeviceUnsolicitedListener() { @Override public void onSttRequest() { // 设备发出 STT 请求,至于是需要进入 `TRANSCRIBE` 或 `TRANSLATE` 由 APP 决策 } }); ```
## 5.8 重启 ```java VNCommon.reboot(new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.9 恢复出厂设置 ```java VNCommon.factoryReset(new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 5.10 解绑设备 ```java VNCommon.unbind(new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
# 6. 应用 系统支持常用的应用场景界面,如实时翻译、题词、导航等,并支持开发者把上位机获取到的实时业务信息发送到设备端呈现。
## 6.1 实时翻译(语音转文字显示)信息同步
系统提供将`实时翻译结果`传输到设备端进行显示的方法,以下是使用步骤: **步骤一:进入翻译应用** ```java // 示例: VNCommon.setView(VNConstant.View.TRANSLATE, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤二:配置界面偏好** - **设置文本显示模式** 语音业务时界面`仅当前`或`含历史`: ```java /** * @param vnAppId 应用,与 setView() 对应。 * @param mode 模式: * VNConstant.SttConfig.TextMode.CURRENT_ONLY - 仅显示当前转写文本 * VNConstant.SttConfig.TextMode.CURRENT_AND_HISTORICAL - 同时显示当前和历史转写文本 * @param vnCommonCallBack 执行结果回调,可为null */ void setTextMode(int vnAppId, int mode, VNCommonCallBack vnCommonCallBack) ```
- **设置译文显示模式** 语音翻译业务时界面`仅显示译文`或`译文和原文都显示`: ```java /** * @param vnAppId 应用,与setView()对应。 * @param mode 模式: * VNConstant.SttConfig.TransMode.TRANSLATION_ONLY - 仅显示翻译文本 * VNConstant.SttConfig.TransMode.ORIGINAL_AND_TRANSLATION - 同时显示翻译文本和原文 * @param vnCommonCallBack 执行结果回调,可为null。 */ void setTransMode(int vnAppId, int mode, VNCommonCallBack vnCommonCallBack) ```
- **设置字号** ```java // 字号配置 FontConfig fontConfig = new FontConfig(); fontConfig.setWeight(30); // 字体大小,整数类型,建议 30 fontConfig.setWordSpace(1); // 字间距,整数类型,控制字符之间的间距 fontConfig.setRowSpace(8); // 行间距,整数类型,控制行与行之间的间距 /** * @param vnAppId 应用,与 setView() 对应。 * @param fontConfig 字号配置。 * @param vnCommonCallBack 执行结果回调,可为 null。 */ void setFontConfig(int vnAppId, FontConfig fontConfig, VNCommonCallBack vnCommonCallBack); ```
- **设置当前语种信息提示** ```java // 语种信息提示配置 LanguageHint languageHint = new LanguageHint(); languageHint.setMode(1); // 0 - 仅显示源语言;1 - 源语言与目标语言双向显示 languageHint.setSource("中文"); languageHint.setTarget("English"); /** * @param vnAppId 应用,与 setView() 对应。 * @param languageHint 语种信息提示配置 * @param vnCommonCallBack 执行结果回调,可为 null。 */ void setLanguageHint(int vnAppId, LanguageHint languageHint, VNCommonCallBack vnCommonCallBack) ```
- **设置当前拾音指示** 指示当前是`手机拾音`或是`眼镜设备拾音`: ```java /** * @param vnAppId 应用,与setView()对应。 * @param audioSource 音源: * VNConstant.SttConfig.AudioSource.PHONE - 使用手机麦克风作为音频输入源 * VNConstant.SttConfig.AudioSource.GLASSES - 使用眼镜设备麦克风作为音频输入源 * @param vnCommonCallBack 执行结果回调,可为null。 */ void setAudioSourceIndicator(int vnAppId, int audioSource, VNCommonCallBack vnCommonCallBack) ``` > 📝 **注意:** 仅图标指示。实际音源切换通过 Android 平台标准 API 实现。
- **设置麦克风拾音方向** 当眼镜设备拾音时,拾音方向为`前向`或`全向`: ```java /** * @param vnAppId 应用,与setView()对应。 * @param micDirectional 拾音方向: * VNConstant.SttConfig.MicDirectional.OMNI - 全向收音,接收来自各个方向的声音 * VNConstant.SttConfig.MicDirectional.FRONT - 定向收音,主要接收正前方向的声音 */ void setMicDirectional(int vnAppId, int micDirectional, VNCommonCallBack vnCommonCallBack) ``` > 📝 **注意:** 仅当前为**眼镜设备拾音**时生效。
**步骤三:发送语音转文字内容** 开发者可以通过`VNSttInfo`描述实时转写的内容和状态,包括消息ID、类型、内容、显示区域等。支持根据**消息ID**进行新增、更新更正、移除对应消息: - `msgId`:消息ID,整数类型,用于多消息同步更新的会话场景,相同msgId的消息会被关联处理。 - `transcribeStr`:转写文本内容,字符串类型 - `translateStr`:翻译文本内容,字符串类型 - `msgType`:消息类型 - `VNConstant.SttInfo.MsgType.STT` 转写内容消息 - `VNConstant.SttInfo.MsgType.HINT` 提示消息,如“正在听...”“网络波动”等提示,HINT类型消息不会进入历史显示。 - `area`:显示区域,对话场景 - `VNConstant.SttInfo.Area.LEFT` 居左 - `VNConstant.SttInfo.Area.RIGHT` 居右 - `VNConstant.SttInfo.Area.CENTER` 居中 - `actionType`:动作类型,用于指定是新建还是更新消息 - `VNConstant.SttInfo.ActionType.NEW` 新建一个语句 - `VNConstant.SttInfo.ActionType.UPDATE` 更新更正语音转文字内容,用于实时场景 - `VNConstant.SttInfo.ActionType.REMOVE` 移除语句 - `isFinal`:最终更正结果标志,如果界面停在 isFinal 条目,则支持划动触控板向前浏览
场景一:顺序推送实时转写结果,不会出现更新历史句、移除某句的场景时,可以不指定`msgId`,而是通过`actionType`来控制句子更新,`NEW`新增一句、`UPDATE`更新更正上一次推送: ```java // 示例:新建一句 VNSttInfo sttInfo = new VNSttInfo(); sttInfo.setTranscribe(transcribeStr); sttInfo.setTranslate(translateStr); sttInfo.setMsgType(VNConstant.SttInfo.MsgType.STT); sttInfo.setActionType(VNConstant.SttInfo.ActionType.NEW); VNCommon.updateSttInfo(vnAppId, sttInfo, null); // 示例:更新上一次推送 VNSttInfo sttInfo = new VNSttInfo(); sttInfo.setTranscribe(transcribeStr); sttInfo.setTranslate(translateStr); sttInfo.setMsgType(VNConstant.SttInfo.MsgType.STT); sttInfo.setActionType(VNConstant.SttInfo.ActionType.UPDATE); VNCommon.updateSttInfo(vnAppId, sttInfo, null); ```
场景二:当 [文本显示模式](#CUSTOM_61_STEP2_setTextMode) 切换为`含历史`时,可能更新历史句,或可能删除某句的业务场景时,需要指定 `msgId` 来实现: ```java // 示例:更新更正msgId句 VNSttInfo sttInfo = new VNSttInfo(); sttInfo.setMsgId(msgId); sttInfo.setTranscribe(transcribeStr); sttInfo.setTranslate(translateStr); sttInfo.setMsgType(VNConstant.SttInfo.MsgType.STT); sttInfo.setActionType(VNConstant.SttInfo.ActionType.UPDATE); VNCommon.updateSttInfo(vnAppId, sttInfo, null); // 示例:移除某msgId句 VNSttInfo sttInfo = new VNSttInfo(); sttInfo.setMsgId(msgId); sttInfo.setActionType(VNConstant.SttInfo.ActionType.REMOVE); VNCommon.updateSttInfo(vnAppId, sttInfo, null); ```
**步骤四:退出转写应用** ```java // 返回主页 VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 6.2 实时转写(语音转文字显示)信息同步 使用步骤同 [6.1 实时翻译(语音转文字显示)信息同步](#61-实时翻译语音转文字显示信息同步),调整: - 将所有vnAppId参数换为VNConstant.View.TRANSCRIBE - 移除sttInfo.setTranscribe(transcribeStr);
## 6.3 对话信息同步 用于语音助手等问答场景,界面支持区分左右条目: 使用步骤同 [6.1 实时翻译(语音转文字显示)信息同步](#61-实时翻译语音转文字显示信息同步),调整: - 将所有vnAppId参数换为 `VNConstant.View.AI`; - 通过sttInfo.setArea()设置该句的显示区域;
## 6.4 导航信息同步 将`实时导航信息`同步至设备端显示的步骤如下:
**步骤一:进入导航应用** ```java // 切换到导航应用界面 VNCommon.setView(VNConstant.View.MAP, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤二:发送导航信息** ```java // 创建导航信息对象 VNNavInfo navInfo = new VNNavInfo(); // 设置导航信息参数 navInfo.setCurStepRetainDistance("500米"); // 当前导航段剩余距离 navInfo.setNextRoadName("前方道路名称"); // 下一条道路名称 navInfo.setSpeed("60km/h"); // 当前行驶速度 navInfo.setRemainDistance("17.2公里"); // 剩余里程 navInfo.setRemainTime("22分钟"); // 剩余时间 navInfo.setNavMode(1); // 导航模式 1-驾驶 Bitmap customIcon = ...; // 自定义图标位图 String iconBmpData = VNCommon.getVenusBmpRawData(customIcon, width, height, true); navInfo.setIconBitmap(iconBmpData); // 发送导航信息到设备 VNCommon.updateNav(navInfo, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` - 图标尺寸建议:48x48,使用 `VNCommon.getVenusBmpRawDataNav(bitmap, 48, 48)`
**步骤三:退出导航应用** ```java // 返回主页 VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 6.5 提词信息同步 本功能支持将`txt`格式的文件同步至设备端显示。 **步骤一:进入提词应用** ```java // 切换到提词应用界面 VNCommon.setView(VNConstant.View.PROMPTER, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤二(可选):设置界面偏好** - **设置是否显示上下文** 界面显示上一页的末行和下一页的首行 ```java // 设置是否显示上下文:0 - 不显示,1 - 显示 VNCommon.setPrompterContextLine(1, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` - **设置字号** ```java // 字号配置 FontConfig fontConfig = new FontConfig(); fontConfig.setWeight(30); // 字体大小,整数类型,建议 30 fontConfig.setWordSpace(1); // 字间距,整数类型,控制字符之间的间距 fontConfig.setRowSpace(8); // 行间距,整数类型,控制行与行之间的间距 /** * @param vnAppId 应用,与setView()对应。 * @param fontConfig 字号配置。 * @param vnCommonCallBack 执行结果回调,可为null。 */ void setFontConfig(int vnAppId, FontConfig fontConfig, VNCommonCallBack vnCommonCallBack); ``` > ⚠️ 重要:不支持提词过程中设置字号,须在设置文件之前完成字号设置
**步骤三:监听提词动态** 获取眼镜设备端实时显示内容和进度 ```java VNCommon.setPrompterListener(new VNPrompterListener() { @Override public void onPageChanged(VNPrompterPage p) { // 进度 int curPage = p.getCurrent(); int totalPage = p.getTotal(); // 当前显示的正文 String curContent = p.getCurText().getContent(); // 文本内容 int curStart = p.getCurText().getStart(); // 在原文档的起始位置(字节) int curEnd = p.getCurText().getEnd(); // 在原文档的结束位置(字节) // 当前显示的上下文 String preContent = p.getPreText().getContent(); int preStart = p.getPreText().getStart(); int preEnd = p.getPreText().getEnd(); String nextContent = p.getNextText().getContent(); int nextStart = p.getNextText().getStart(); int nextEnd = p.getNextText().getEnd(); } @Override public void onLoadStart() { // 文档加载开始。根据文档大小,加载时间不同,加载过程中须提示用户 } @Override public void onLoadEnd() { // 文档加载完成。完成后可以设置目标页面。 } }); ```
**步骤四:设置提词文档** 将当前App可访问的`txt`文件通过setPrompterFile接口通知设备端进行加载: onSuccess():加载成功,进行下一步,参考 [显示目标页面](#CUSTOM_65_STEP5) 的说明; onFailed():加载失败,需通过 [上传文件](#CUSTOM_55_3) 后重试。 ```java // 示例:将file设置为题词文件 VNCommon.setPrompterFile(file, new VNCommonCallBack() { @Override public void onSuccess() { // 设备端检查文件通过,进行下一步,设置页面显示 } @Override public void onTimeOut() { // 检查超时,提示用户或重试 } @Override public void onFailed() { // 设备端检查文件未通过,需上传file文件后再试 } }); ``` > ⚠️ **重要:** 仅支持utf-8编码的txt格式文档 > 📝 **注意:** 建议文件大小不超过 30 KB
**步骤五:显示目标页面** 当文档设置成功后,通过此接口显示目标页面: ```java // 示例:显示首页 VNPrompterPage vnPrompterPage = new VNPrompterPage(); vnPrompterPage.setCurrent(1); VNCommon.setPrompterPage(vnPrompterPage, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤六:翻页** 可通过设备触控区域前后滑动翻页,也可通过调用API发送翻页指令: ```java // 示例:前一页 VNCommon.setPrompterPageUp(new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); // 示例:后一页 VNCommon.setPrompterPageDown(new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤七:退出题词** ```java // 示例:返回主页 VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
## 6.6 图库 **步骤一:进入图库应用** ```java VNCommon.setView(VNConstant.View.GALLERY, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
**步骤二:显示图片** - **显示已在眼镜设备上存在的图片** 通过 [文件列表](#CUSTOM_55_2) 获取Gallery类型的VNFile列表,选择列表中文件显示: ```java // 示例:或通过设备端文件对象 VNCommon.setGalleryFile(vnFile, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ``` - **上传 APP 端图片到眼镜设备并显示** 通过 [上传文件](#CUSTOM_55_3) 上传Gallery类型的file文件,上传成功后显示: ```java // 示例: File file = new File("/xxx/xxx.jpg"); VNCommon.setGalleryFile(file, new VNCommonCallBack() { @Override public void onSuccess() { // 设备端检查文件通过,显示图片 } @Override public void onTimeOut() { // 检查超时,提示用户或重试 } @Override public void onFailed() { // 设备端检查文件未通过,需上传file文件后再试 } }); ``` > **⚠️ 重要:** 图片文件需由 APP 端预处理: > - 分辨率:根据设备型号查询 > - 文件大小:建议不超过 200 KB > - 图像:灰度图
**步骤三:退出图库** ```java // 示例:返回主页 VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); ```
# 7. 应用定制 联系我们
# 8. 固件升级 固件升级服务通过专用数据通路(VNOTA)工作,在进行固件升级之前,需要先断开与设备的消息服务通路(VNCommon):
``` +-------------+ +------------+ +-----------+ | Application | | VNCommon | | VNOTA | +-------------+ +------------+ +-----------+ | | | | 检查VNCommon连接状态 | | |---------------------->| | | | | | 如果已连接,断开VNCommon | |---------------------->| | | | | | 等待VNCommon完全断开 | | | | | | 初始化VNOTA | | |--------------------------------------------->| | | | | 连接VNOTA | | |--------------------------------------------->| | | | | | onConnected | |<---------------------------------------------| | | | | | onStateChanged(2305) | |<---------------------------------------------| | | | | 开始OTA升级 | | |--------------------------------------------->| | | | | | onProgressChanged | |<---------------------------------------------| | | | | | onSuccess/onError| |<---------------------------------------------| | | | | 断开VNOTA连接 | | |--------------------------------------------->| | | | | | onDisconnected | |<---------------------------------------------| | | | | 重新连接VNCommon | | |---------------------->| | | | | ```
1. **准备阶段** - 检查设备电量是否满足升级要求,建议电量在 40% 以上; - 检查OTA文件是否有效,且本地存储路径可访问。
2. **断开VNCommon连接** - 如有自动重连机制,请停止; - 断开VNCommon连接: `VNCommon.disconnect()`; - 等待并确认VNCommon已断开。 ```java // 断开消息服务通路 VNCommon.disconnect(); // 检查连接状态,如通过轮询 new Runnable() { @Override public void run() { if (retryCount < maxRetries) { if (VNCommon.isConnected()) { retryCount++; handler.postDelayed(this, 1000); } else { // TODO 已断开连接,可以进行固件升级操作 } } } }; // 确认断开连接后再进行固件升级操作 ```
3. **设置OTA状态监听** ```java VNOTA.setOtaServiceListener(new VNOtaServiceListener() { @Override public void onConnected() { // 服务已连接 } @Override public void onDisconnected() { // 服务已断开 } @Override public void onStateChanged(int state, String msg) { // 升级过程中阶段变化提示 if (state == 2305) { VNOTA.startOta(); } } @Override public void onProgressChanged(String progress) { // 升级进度变更 } @Override public void onSuccess() { // OTA升级成功 // TODO VNCommon.connect() } @Override public void onError(int code, String msg) { // OTA升级失败 // code: 错误码,具体定义参考 VNConstant.Ota.ErrorCode // msg: 错误信息 } }); ```
4. **初始化并连接VNOTA** ```java BluetoothDevice device = null; // 蓝牙设备实例 String otaFilePath = ""; // 升级文件路径 int otaUser = VNConstant.Ota.User.FIRMWARE; // FIRMWARE表示固件升级 VNOTA.initOta(device, otaFilePath, otaUser); //连接设备的OTA服务链路 VNOTA.connect(device) ```
5. **执行OTA升级** - 在VNOTA连接成功后SDK内部会开始协商,请等待`onStateChanged` - ⚠️ 重要:当`onStateChanged`收到 `state == 2305` 时,开始OTA: `VNOTA.startOta()` - 通过监听器接收升级进度: `onProgressChanged()` ```java ... @Override public void onStateChanged(int state, String msg) { if (state == 2305) { VNOTA.startOta(); } } ... ```
5. **OTA完成处理** - 升级成功: `onSuccess()` - 断开VNOTA连接: `VNOTA.disconnect()`; - 如有,清除本地设备信息,待重新连接后获取升级后的设备信息; - 建立VNCommon连接:`VNCommon.disconnect()`。 - 升级失败: `onError()` - 断开VNOTA连接: `VNOTA.disconnect()`; - 显示错误对话框,重试或退出。
> 📝 **注意:** > 1. 在进行 OTA 升级时,需要确保设备电量充足(至少 40%); > 2. OTA 升级过程中不应中断,可能导致设备固件损坏; > 3. 在 OTA 升级完成后,正常情况下设备会自动重启,启动时间比正常开机用时长 1 - 2 分钟。
# 9. 常见问题
## 9.1 设备无法扫描到 - 检查设备是否开机并停留在蓝牙配对界面 - 检查设备是否已与其他终端配对并连接
## 9.2 设备没有声音 - 检查系统蓝牙连接状态,需要 A2DP、HFP 连接正常
# 10. 更新历史