52 KiB
VenusSDK接入与开发指南(Android)vX.X.X
1. 文档概述
本文介绍在 Android 平台上集成 VenusSDK 的方法,实现应用与 VenusOS 智能眼镜的连接与交互,包括设备连接、设备信息获取、设备状态同步、系统设置、固件升级、以及各项功能(实时语音转文字服务、导航、提词)的信息同步。
2. 支持平台与版本
- Android 7.0 及以上
- minSdk 24 及以上
- 支持 Classic Bluetooth 连接
3. 快速开始
3.1 集成SDK
- 将
VenusSDK_vx.x.x_release.aar复制到 Application Module/libs 文件夹 - 在 app 的 build.gradle.kts 中添加依赖:
dependencies {
implementation(files("libs/VenusSDK_vx.x.x_release.aar"))
}
3.2 声明权限
根据场景需要,在 /app/src/main/AndroidManifest.xml 文件中申请获取相应的设备权限:
<!-- 访问网络权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 用于 SDK 获取网络状态变化 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 麦克风权限,用于语音消息时录制语音,不使用录制语音可以移除 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 获取运营商信息,用于获取网络状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- 读取存储权限,用于附件等的获取 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 访问 GPS 定位,用于定位消息,如果不用定位相关可以移除 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 允许程序在手机屏幕关闭后后台进程仍然运行 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
3.3 混淆配置
在 app/proguard-rules.pro 文件中添加:
-keep class com.jueyuantech.venussdk.** { *; }
-dontwarn com.jueyuantech.venussdk.**
3.4 SDK初始化
VenusSDK 主要提供:VNSDK、VNCommon 和 VNOTA 接口:
VNSDK负责 SDK 初始化、自定义参数、获取版本构建信息等;VNCommon负责处理与设备相关的常用功能,如设备连接管理、系统配置、状态监听和功能调用等;VNOTA负责固件升级相关功能。
在 Application 类中初始化 SDK:
VNSDK.init(this, new VNOptions());
📝 注意: 调用
VNSDK.init后,SDK 内部同时会对 VNCommon 和 VNOTA 进行初始化,开发者无需手动初始化,可直接调用其功能。
3.5 获取SDK构建信息
获取SDK的版本构建信息:
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自行维护。
- 初始化设备:
VNCommon.initDevice(bluetoothDevice);
- 设置连接状态监听:
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;
}
}
});
- 连接设备:
VNCommon.connect(bluetoothDevice);
- 获取当前连接状态:
boolean connected = VNCommon.isConnected();
- 断开连接:
VNCommon.disconnect();
4.3 设备信息获取
通过getDeviceInfo方法获取设备的基本信息,包括设备名称、MAC地址、固件版本等信息:
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方法获取当前系统的各项配置信息,包括亮度、自动亮度调节、字体大小、系统语言、佩戴检测、触控板等状态:
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 在设备连接成功时自动设置,正常情况下无需开发者进行设置。
在检测到应用终端时间发生改变的情况下,需开发者主动调用以同步时间:
/**
* @param timeConfig 时间配置:时间、格式等
*/
void setTimeConfig(TimeConfig timeConfig, VNCommonCallBack vnCommonCallBack)
// 示例:
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时间与眼镜设备系统时间不一致,以下功能会受影响:
历史固件版本设置时间方法:
/**
* @param time 时间戳,单位:秒
* @deprecated prefer setTimeConfig
*/
void setTime(long time, VNCommonCallBack vnCommonCallBack)
// 示例:
VNCommon.setTime(System.currentTimeMillis() / 1000, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
4.6 亮度设置
手动设置亮度:
/**
* @param brightness 0 - 255
*/
void setBrightness(int brightness, VNCommonCallBack vnCommonCallBack)
// 示例:设置亮度值为 128
VNCommon.setBrightness(128, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
自动亮度调节开关:
/**
* @param enabled
* VNConstant.EnableState.ENABLED - 开启
* VNConstant.EnableState.DISABLED - 关闭
*/
void setAutoBrightnessEnabled(int enabled, VNCommonCallBack vnCommonCallBack)
// 示例:开启自动亮度功能
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 显示模式设置
支持显示模式设置,如全屏显示、半屏显示:
/**
* @param displayConfig 显示配置:显示模式、显示区域等配置。
*/
void setDisplayConfig(DisplayConfig displayConfig, VNCommonCallBack vnCommonCallBack)
// 示例:
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 系统语言设置
系统界面语言设置:
/**
* @param language BCP 47 语言代码
*/
void setLanguage(String language, VNCommonCallBack vnCommonCallBack)
// 示例:设置系统语言为中文
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 通知 或 ANCS(苹果通知中心服务)向设备发送通知信息。
设置通知功能的开关状态:
/**
* @param enabled
* VNConstant.EnableState.ENABLED - 开启
* VNConstant.EnableState.DISABLED - 关闭
*/
void setNotificationEnabled(int enabled, VNCommonCallBack vnCommonCallBack)
// 示例:开启通知功能
VNCommon.setNotificationEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
📝 注意: 5.4 通知 中的系统通知不受该设置影响。
4.11 触控板设置
用户可以通过眼镜设备的触控区域进行单击、双击、长按、滑动等手势与设备交互。
设置触控板功能的开关状态:
/**
* @param enabled
* VNConstant.EnableState.ENABLED - 开启
* VNConstant.EnableState.DISABLED - 关闭
*/
void setTouchpadEnabled(int enabled, VNCommonCallBack vnCommonCallBack)
// 示例:开启触控板
VNCommon.setTouchpadEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
使用场景:
- 菜单导航:快速浏览和切换不同功能界面
- 内容控制:确认选择、返回上级等操作
- 特殊场景:在不方便使用语音控制时提供替代操作方式
📝 注意: 此功能需设备硬件支持。
4.12 静置状态自动熄屏设置
通过设备的静置传感器检测设备是否处于静置状态(如放置在桌面)。当检测到设备静置超过 10 秒时,系统自动熄屏。
设置静置熄屏功能的开关状态:
/**
* @param enabled
* VNConstant.EnableState.ENABLED - 开启
* VNConstant.EnableState.DISABLED - 关闭
*/
void setIdleDetectionEnabled(int enabled, VNCommonCallBack vnCommonCallBack)
// 示例:开启功能
VNCommon.setIdleDetectionEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
使用场景:
- 自动熄屏:用户将设备放置不动时自动进入熄屏模式
- 节能管理:通过自动熄屏机制延长设备使用时间
📝 注意:
- 此功能需设备硬件支持。
- 在任意功能界面进入熄屏后,30 秒会收到 系统状态监听 的
onViewChanged(int vnAppId)退回HOME主界面的消息。
4.13 非活跃状态自动熄屏设置
非活跃状态监听,是指设备监听超过一段时间(timeout)无新消息抵达设备,与设备无消息交互,则设备自动熄屏。
/**
* @param timeout 单位:秒,0 表示关闭
*/
void setInactivityTimeout(int timeout, VNCommonCallBack vnCommonCallBack)
// 示例:设置无交互 1 分钟后自动熄屏
VNCommon.setInactivityTimeout(60, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
📝 注意:
- 在任意功能界面进入熄屏后,30 秒会收到 系统状态监听 的
onViewChanged(int vnAppId)退回HOME主界面的消息。- 在特殊场景(如提词)需要保持亮屏时,可周期性(间隔低于 timeout)调用
VNCommon.sendKeepAlive()发送保活信号。
4.14 熄屏状态自动关机设置
设备支持熄屏一段时间(timeout)后自动关机设置:
/**
* @param timeout 单位:秒,0 表示关闭
*/
void setPoweroffTimeout(int timeout, VNCommonCallBack vnCommonCallBack)
// 示例:设置熄屏 5 分钟后自动关机
VNCommon.setPoweroffTimeout(300, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
4.15 佩戴检测设置
开启佩戴检测后,当用户戴上设备时自动亮屏,摘下设备时自动熄屏:
/**
* @param enabled
* VNConstant.EnableState.ENABLED - 开启
* VNConstant.EnableState.DISABLED - 关闭
*/
void setWearDetectionEnabled(int enabled, VNCommonCallBack vnCommonCallBack)
// 示例:
VNCommon.setWearDetectionEnabled(VNConstant.EnableState.ENABLED, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
📝 注意: 此功能需设备硬件支持。
5 系统状态和操控
用户可以实时获取系统当前的各种状态、事件,结合业务场景来设计实现各项交互:
运行状态:熄屏、亮屏充电状态:正在充电、未在充电电池电量应用的进入和退出触控事件:长按、双击、前滑、后滑系统主动上报消息:语音业务请求等
5.1 获取、监听、设置系统状态
- 系统状态监听
通过setDeviceStatusListener方法设置设备状态监听器,可以监听设备的系统状态、充电状态、电池电量、应用切换等变化,以及触控板按键事件:
// 设置设备状态监听
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:
}
}
});
- 通过
getSystemStatus方法主动获取设备当时的运行状态,包括系统状态、充电状态、电池电量等:
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) {
// 获取设备状态失败
}
});
- 在特殊场景下,开发者可主动设置系统运行状态:
/**
* @param sysState
* VNConstant.SysState.SCREEN_ON - 亮屏状态
* VNConstant.SysState.SCREEN_OFF - 熄屏状态
*/
void setSysState(int sysState, VNCommonCallBack vnCommonCallBack)
// 示例:将设备熄屏
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 触控板
开发者可通过 系统状态监听 中的 onTouchEvent(int event) 回调方法监听到未被设备消费的触摸事件。
在特殊场景下,支持开发者主动发送触摸事件:
/**
* @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)
// 示例:发送长按事件
VNCommon.sendTouchEvent(VNConstant.TouchEvent.LONG_PRESS);
5.3 应用的进入和退出
当系统被触控板或其他途径操控进入和退出应用时,开发者通过 系统状态监听 中的 onViewChanged(int vnAppId) 回调方法监听到相应的请求。
也可以主动进行应用跳转:
/**
* @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)
// 示例:进入翻译应用界面
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() { }
});
获取设备当前所在应用:
void getView(VNViewCallBack vnViewCallBack)
// 示例:获取设备当前所在应用
VNCommon.getView(new VNViewCallBack() {
@Override
public void onSuccess(int vnAppId) {
// vnAppId 参考 VNConstant.View
}
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
5.4 通知
系统支持在界面上方与用户进行通知交互:
- 显示通知:
/**
* @param vnNotificationInfo
* (必选)id - 区分通知用于更新、移除
* (必选)title - 标题
* (必选)msg - 内容
* (必选)type - 通知类型:0-用户,1-系统
* (必选)duration - 持续时间,单位:秒;0 - 常驻等待关闭,n - 时间到自动关闭
* (必选)timeConfig - 通知时间
*/
void addNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack)
参数说明:
- 类型
type:0 - 用户:当 4.10 通知功能设置 关闭时,用户通知将被过滤不显示;1 - 系统:不受 4.10 通知功能设置 状态影响
- 持续时间
duration:0 - 常驻等待关闭:显示后需调用 移除通知 关闭,或通过双击触控板关闭n - 时间到自动关闭:n 秒时间到后自动关闭
// 示例:显示通知:
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() { }
});
- 更新通知:
/**
* @param vnNotificationInfo
* (必选)id - 区分通知用于更新、移除
* (可选)msg - 内容
*/
void updateNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack)
// 示例:更新已有通知的内容
notificationInfo.setId(1000);
notificationInfo.setMsg("更新后的通知内容");
VNCommon.updateNotification(notificationInfo, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
- 移除通知:
/**
* @param vnNotificationInfo
* (必选)id - 区分通知用于更新、移除
*/
void removeNotification(VNNotificationInfo vnNotificationInfo, VNCommonCallBack vnCommonCallBack)
// 示例:移除指定ID的通知
notificationInfo.setId(1000);
VNCommon.removeNotification(notificationInfo, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
5.5 文件系统
系统支持用户在 提词信息同步、 图库等应用场景下,对设备文件进行管理。如查看设备上当前已上传的提词文件列表、上传新文件等等操作。
- 文件描述
VNFile用于描述设备中的文件信息,包括文件名,文件/文件夹,大小等描述。
部分 API 接收 VNFile 参数时,开发者可通过接口将 File 转为 VNFile:
/**
* @param file 原文件
* @param vnFileType 应用场景
* VNConstant.VNFile.Type.PROMPTER - 题词
* VNConstant.VNFile.Type.GALLERY - 图库
* @return VNFile 设备文件描述
*/
VNFile initVNFile(File file, int vnFileType)
// 示例:将本地文件转为题词文件描述
File file = new File("/xxx/xxx.txt");
VNFile vnFile = initVNFile(file, VNConstant.VNFile.Type.GALLERY);
- 文件列表
/**
* @param vnFileType 应用场景
* VNConstant.VNFile.Type.PROMPTER - 题词
* VNConstant.VNFile.Type.GALLERY - 图库
*/
void getFileList(int vnFileType, VNFileListCallBack vnFileListCallBack)
// 示例:获取设备端题词场景文件列表
VNCommon.getFileList(VNConstant.VNFile.Type.PROMPTER, new VNFileListCallBack() {
@Override public void onSuccess(List<VNFile> files) { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
- 上传文件
上传本地文件至设备指定应用场景中:
// 示例:上传本地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();
- 删除文件
/**
* @param vnFile 设备文件描述
* @param vnCommonCallBack 执行结果回调
*/
VNCommon.removeFile(VNFile vnFile, VNCommonCallBack vnCommonCallBack)
// 示例:删除由getFileList获取到的设备文件列表中的某文件
VNCommon.removeFile(vnFile, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
- 清空目录
/**
* @param vnFileType 应用场景
* VNConstant.VNFile.Type.PROMPTER - 题词
* VNConstant.VNFile.Type.GALLERY - 图库
* @param vnCommonCallBack 执行结果回调
*/
void clearFolder(int vnFileType, VNCommonCallBack vnCommonCallBack)
// 示例:清空题词文件目录
VNCommon.clearFolder(VNConstant.VNFile.Type.PROMPTER, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
- 检查本地文件是否在设备存在
通常情况下,如果本地目标文件在设备端已经存在,则不需要重新上传。判断是否存在:
/**
* @param file 原文件
* @param vnFileType 应用场景
* VNConstant.VNFile.Type.PROMPTER - 题词
* VNConstant.VNFile.Type.GALLERY - 图库
* @param vnCommonCallBack 执行结果回调
*/
void isFileExist(File file, int vnFileType, VNCommonCallBack vnCommonCallBack)
VNCommon.isFileExist(file, VNConstant.VNFile.Type.GALLERY, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
5.6 查看存储空间
/**
* @param vnRomUsageCallBack 查询结果回调
*/
void getRomUsage(VNRomUsageCallBack vnRomUsageCallBack)
// 示例:查询设备存储空间情况
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 监听设备主动消息
监听由眼镜设备主动上报的请求,如唤醒、助手等业务:
// 示例:设置设备主动上报监听
VNCommon.setDeviceUnsolicitedListener(new VNDeviceUnsolicitedListener() {
@Override
public void onSttRequest() {
// 设备发出 STT 请求,至于是需要进入 `TRANSCRIBE` 或 `TRANSLATE` 由 APP 决策
}
});
5.8 重启
VNCommon.reboot(new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
5.9 恢复出厂设置
VNCommon.factoryReset(new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
5.10 解绑设备
VNCommon.unbind(new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
6. 应用
系统支持常用的应用场景界面,如实时翻译、题词、导航等,并支持开发者把上位机获取到的实时业务信息发送到设备端呈现。
6.1 实时翻译(语音转文字显示)信息同步
系统提供将实时翻译结果传输到设备端进行显示的方法,以下是使用步骤:
步骤一:进入翻译应用
// 示例:
VNCommon.setView(VNConstant.View.TRANSLATE, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
步骤二:配置界面偏好
- 设置文本显示模式 语音业务时界面
仅当前或含历史:/** * @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)
- 设置译文显示模式 语音翻译业务时界面
仅显示译文或译文和原文都显示:/** * @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)
-
设置字号
// 字号配置 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);
-
设置当前语种信息提示
// 语种信息提示配置 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)
-
设置当前拾音指示 指示当前是
手机拾音或是眼镜设备拾音:/** * @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 实现。
-
设置麦克风拾音方向 当眼镜设备拾音时,拾音方向为
前向或全向:/** * @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更新更正上一次推送:
// 示例:新建一句
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);
场景二:当 文本显示模式 切换为含历史时,可能更新历史句,或可能删除某句的业务场景时,需要指定 msgId 来实现:
// 示例:更新更正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);
步骤四:退出转写应用
// 返回主页
VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
6.2 实时转写(语音转文字显示)信息同步
使用步骤同 6.1 实时翻译(语音转文字显示)信息同步,调整:
- 将所有vnAppId参数换为VNConstant.View.TRANSCRIBE
- 移除sttInfo.setTranscribe(transcribeStr);
6.3 对话信息同步
用于语音助手等问答场景,界面支持区分左右条目: 使用步骤同 6.1 实时翻译(语音转文字显示)信息同步,调整:
- 将所有vnAppId参数换为
VNConstant.View.AI; - 通过sttInfo.setArea()设置该句的显示区域;
6.4 导航信息同步
将实时导航信息同步至设备端显示的步骤如下:
步骤一:进入导航应用
// 切换到导航应用界面
VNCommon.setView(VNConstant.View.MAP, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
步骤二:发送导航信息
// 创建导航信息对象
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)
步骤三:退出导航应用
// 返回主页
VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
6.5 提词信息同步
本功能支持将txt格式的文件同步至设备端显示。
步骤一:进入提词应用
// 切换到提词应用界面
VNCommon.setView(VNConstant.View.PROMPTER, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
步骤二(可选):设置界面偏好
-
设置是否显示上下文 界面显示上一页的末行和下一页的首行
// 设置是否显示上下文:0 - 不显示,1 - 显示 VNCommon.setPrompterContextLine(1, new VNCommonCallBack() { @Override public void onSuccess() { } @Override public void onTimeOut() { } @Override public void onFailed() { } }); -
设置字号
// 字号配置 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);⚠️ 重要:不支持提词过程中设置字号,须在设置文件之前完成字号设置
步骤三:监听提词动态 获取眼镜设备端实时显示内容和进度
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():加载成功,进行下一步,参考 显示目标页面 的说明;
onFailed():加载失败,需通过 上传文件 后重试。
// 示例:将file设置为题词文件
VNCommon.setPrompterFile(file, new VNCommonCallBack() {
@Override
public void onSuccess() {
// 设备端检查文件通过,进行下一步,设置页面显示
}
@Override
public void onTimeOut() {
// 检查超时,提示用户或重试
}
@Override
public void onFailed() {
// 设备端检查文件未通过,需上传file文件后再试
}
});
⚠️ 重要: 仅支持utf-8编码的txt格式文档 📝 注意: 建议文件大小不超过 30 KB
步骤五:显示目标页面
当文档设置成功后,通过此接口显示目标页面:
// 示例:显示首页
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发送翻页指令:
// 示例:前一页
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() { }
});
步骤七:退出题词
// 示例:返回主页
VNCommon.setView(VNConstant.View.HOME, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
6.6 图库
步骤一:进入图库应用
VNCommon.setView(VNConstant.View.GALLERY, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
步骤二:显示图片
- 显示已在眼镜设备上存在的图片 通过 文件列表 获取Gallery类型的VNFile列表,选择列表中文件显示:
// 示例:或通过设备端文件对象
VNCommon.setGalleryFile(vnFile, new VNCommonCallBack() {
@Override public void onSuccess() { }
@Override public void onTimeOut() { }
@Override public void onFailed() { }
});
- 上传 APP 端图片到眼镜设备并显示 通过 上传文件 上传Gallery类型的file文件,上传成功后显示:
// 示例:
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
- 图像:灰度图
步骤三:退出图库
// 示例:返回主页
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 | |
|---------------------->| |
| | |
- 准备阶段
- 检查设备电量是否满足升级要求,建议电量在 40% 以上;
- 检查OTA文件是否有效,且本地存储路径可访问。
- 断开VNCommon连接
- 如有自动重连机制,请停止;
- 断开VNCommon连接:
VNCommon.disconnect(); - 等待并确认VNCommon已断开。
// 断开消息服务通路
VNCommon.disconnect();
// 检查连接状态,如通过轮询
new Runnable() {
@Override
public void run() {
if (retryCount < maxRetries) {
if (VNCommon.isConnected()) {
retryCount++;
handler.postDelayed(this, 1000);
} else {
// TODO 已断开连接,可以进行固件升级操作
}
}
}
};
// 确认断开连接后再进行固件升级操作
- 设置OTA状态监听
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: 错误信息
}
});
- 初始化并连接VNOTA
BluetoothDevice device = null; // 蓝牙设备实例
String otaFilePath = ""; // 升级文件路径
int otaUser = VNConstant.Ota.User.FIRMWARE; // FIRMWARE表示固件升级
VNOTA.initOta(device, otaFilePath, otaUser);
//连接设备的OTA服务链路
VNOTA.connect(device)
- 执行OTA升级
- 在VNOTA连接成功后SDK内部会开始协商,请等待
onStateChanged - ⚠️ 重要:当
onStateChanged收到state == 2305时,开始OTA:VNOTA.startOta() - 通过监听器接收升级进度:
onProgressChanged()
- 在VNOTA连接成功后SDK内部会开始协商,请等待
...
@Override
public void onStateChanged(int state, String msg) {
if (state == 2305) {
VNOTA.startOta();
}
}
...
- OTA完成处理
-
升级成功:
onSuccess()- 断开VNOTA连接:
VNOTA.disconnect(); - 如有,清除本地设备信息,待重新连接后获取升级后的设备信息;
- 建立VNCommon连接:
VNCommon.disconnect()。
- 断开VNOTA连接:
-
升级失败:
onError()- 断开VNOTA连接:
VNOTA.disconnect(); - 显示错误对话框,重试或退出。
- 断开VNOTA连接:
-
📝 注意:
- 在进行 OTA 升级时,需要确保设备电量充足(至少 40%);
- OTA 升级过程中不应中断,可能导致设备固件损坏;
- 在 OTA 升级完成后,正常情况下设备会自动重启,启动时间比正常开机用时长 1 - 2 分钟。
9. 常见问题
9.1 设备无法扫描到
- 检查设备是否开机并停留在蓝牙配对界面
- 检查设备是否已与其他终端配对并连接
9.2 设备没有声音
- 检查系统蓝牙连接状态,需要 A2DP、HFP 连接正常