AI语音助手
AI语音助手(AI Voice Assistant)是 HealthAide 健康助手 App 中基于讯飞(iFlytek)AI 能力与 RCSP 蓝牙协议构建的语音交互子系统,负责语音识别(ASR/IAT)、大模型对话(Chat/SparkChain)、语音合成(TTS)以及 AI 表盘(AI Dial)的端云协同,让用户通过语音与智能手表完成健康问答与交互。
Purpose and Scope
本页面聚焦于 com.jieli.healthaide.tool.aiui 包及其数据层、配置资源,覆盖:
- AI 能力编排核心:
AIManager门面类如何协调 IAT(语音识别)、Chat(星火大模型对话)、TTS(语音合成)三条 AI 管线; - Handler 任务体系:
BaseAIHandler抽象基类及其派生的对话、云端服务、AI 表盘、语音识别四类处理器; - 讯飞封装层:
IflytekChatWrapper/IflytekIatWrapper/IflytekTtsWrapper/IflytekAIDialStyleHelper; - 手表侧 RCSP 通道:
AIDialWrapper/AIRecordWrapper/AICloudServeWrapper及监听器; - 消息持久化:
AICloudMessageEntity/AICloudMessageDao; - 资源与依赖:
aiui_phone.cfg与 SparkChain SDK。
以下内容属于相邻页面、不在本页展开:蓝牙连接管理(RCSP 协议基础)见「WatchManager / RCSP 通信」相关页面;健康数据采集与命令处理见「健康数据」相关页面;App 整体启动流程见「HealthApplication」相关页面。
Overview
AI 语音助手的核心设计意图是:让手表端的语音交互能力由手机端代为完成。智能手表受限于算力、功耗与存储,无法本地运行大模型,因此 HealthAide App 通过蓝牙 RCSP 通道接收手表端录制的语音数据(AIRecordWrapper),在手机端完成三阶段处理:
- 听(Listen):
IflytekIatWrapper将录音转为文本(ASR / IAT,Speech-to-Text); - 想(Think):
IflytekChatWrapper基于讯飞星火大模型(SparkChain SDK)生成回答文本; - 说(Speak):
IflytekTtsWrapper将回答文本合成为语音(TTS,Text-to-Speech),再经 RCSP 通道回传手表播放。
同时,系统还支持 AI 表盘(AI Dial) 场景:当手表进入 AI 表盘界面(设备通知 state == 1)时,AIManager 自动启动录音处理,将 IAT 识别结果直接路由给 AIDialHandler 进行对话式问答,并在设备退出表盘(state == 0)时停止处理并清理等待弹窗。
整个子系统采用「门面 + 策略处理器」架构:AIManager 是唯一对外门面,持有具体实现类;BaseAIHandler 体系定义了任务边界;后续接入其他 AI 供应商时只需新增 BaseAIHandler 的实现类并替换 AIManager 中的装配即可,体现了面向接口编程与策略模式的设计意图。
Architecture
下图展示了 AI 语音助手子系统的整体架构与数据流:
flowchart TD
subgraph sg_Device["手表端 (BLE 对端)"]
Watch["智能手表<br/>AI 表盘 / 录音 / 播放"]
end
subgraph sg_App["HealthAide App (手机端)"]
subgraph sg_Entry["入口层"]
HealthApp["HealthApplication.onCreate<br/>IflytekAIDialStyleHelper.init"]
end
subgraph sg_Facade["门面层"]
AIManager["AIManager<br/>AI 管理门面"]
end
subgraph sg_Handler["任务处理器层 (handle 包)"]
BaseAIHandler["BaseAIHandler (抽象基类)"]
IatHandler["BaseAIIatHandler<br/>IflytekAIIatHandler (语音识别)"]
ChatHandler["BaseAIChatHandler (对话基类)"]
DialHandler["BaseAIDialHandler<br/>IflytekAIDialHandler (AI 表盘对话)"]
CloudHandler["BaseAICloudServeHandler<br/>IflytekAICloudServeHandler (云端服务)"]
end
subgraph sg_Iflytek["讯飞 AI 封装层 (iflytek 包)"]
IatWrapper["IflytekIatWrapper (ASR 识别)"]
ChatWrapper["IflytekChatWrapper (星火大模型)"]
TtsWrapper["IflytekTtsWrapper (TTS 合成)"]
DialStyle["IflytekAIDialStyleHelper (表盘风格)"]
end
subgraph sg_Rcsp["RCSP 通道封装层 (rcsp 包)"]
RecordWrapper["AIRecordWrapper (录音数据)"]
DialWrapper["AIDialWrapper + AIDialListener (AI 表盘)"]
CloudWrapper["AICloudServeWrapper + Listener (云端服务)"]
end
subgraph sg_Data["数据层"]
Entity["AICloudMessageEntity"]
Dao["AICloudMessageDao"]
end
end
subgraph sg_Cloud["云端服务"]
Spark["讯飞星火大模型 (SparkChain)"]
IflyCloud["讯飞 AIUI 云端"]
end
Watch -->|"BLE / RCSP 录音数据"| RecordWrapper
RecordWrapper --> IatHandler
IatHandler --> IatWrapper
IatWrapper -->|"文本"| ChatHandler
ChatHandler --> ChatWrapper
ChatWrapper -->|"对话文本"| Spark
ChatHandler --> DialHandler
DialHandler --> TtsWrapper
TtsWrapper -->|"合成语音"| DialWrapper
DialWrapper -->|"RCSP 回传"| Watch
CloudHandler --> CloudWrapper
CloudWrapper --> IflyCloud
CloudHandler --> Entity
Entity --> Dao
HealthApp --> AIManager
AIManager --> IatHandler
AIManager --> ChatHandler
AIManager --> DialHandler
AIManager --> CloudHandler
AIManager --> RecordWrapper
AIManager --> DialWrapper
AIManager --> CloudWrapper
AIManager --> DialStyle
BaseAIHandler <|-- IatHandler
BaseAIHandler <|-- DialHandler
BaseAIHandler <|-- CloudHandler
BaseAIHandler <|-- ChatHandler
架构分层说明
| 层次 | 关键类 | 职责 |
|---|---|---|
| 入口层 | HealthApplication | 应用启动时调用 IflytekAIDialStyleHelper.init(this) 初始化 AI 表盘风格助手(见 HealthApplication.java) |
| 门面层 | AIManager | 持有所有 AI 组件实例,监听设备状态事件,编排录音→识别→对话→合成→回传的完整链路 |
| 任务处理器层 | BaseAIHandler 及四个派生类 | 定义 AI 任务生命周期(release()、isConnected()),按业务域拆分处理器 |
| 讯飞封装层 | Iflytek*Wrapper | 直接调用讯飞 SDK(IAT/星火/TTS),屏蔽供应商 API 差异 |
| RCSP 通道层 | AIDialWrapper 等 | 通过 WatchManager 与手表交换录音、表盘状态、云端服务数据 |
| 数据层 | AICloudMessageEntity/Dao | 云端服务消息的本地持久化 |
设计意图分析
- 门面模式(Facade):
AIManager是 UI/Service 层访问 AI 能力的唯一入口,屏蔽了讯飞 SDK 与 RCSP 协议的复杂度; - 策略模式(Strategy):
BaseAIHandler抽象出任务契约,Iflytek*是讯飞策略实现,未来可替换为其他供应商而不影响调用方; - 关注点分离:讯飞封装(iflytek 包)与 RCSP 通道(rcsp 包)相互独立,由
AIManager在中间装配,降低供应商 SDK 与设备协议之间的耦合。
主内容:核心实现详解
AIManager —— AI 能力编排门面
AIManager(类注释描述为"AI管理",作者 ZhangHuanMing,创建于 2023/9/18)是子系统的核心门面,通过组合持有全部 AI 组件:
public class AIManager {
private static final String TAG = "AIManager";
private Context mContext;
private WatchManager mRcspOp;
private IflytekChatWrapper mIflytekChatWrapper; // 星火大模型对话
private IflytekTtsWrapper mIflytekTtsWrapper; // 语音合成
private IflytekIatWrapper mIflytekIatWrapper; // 语音识别
private AIRecordWrapper mAIRecordWrapper; // 手表录音数据
private AICloudServeWrapper mAICloudServeWrapper; // 云端服务
private AIDialWrapper mAIDialWrapper; // AI 表盘通道
private BaseAIIatHandler mAIIatHandler; // 识别任务
private BaseAICloudServeHandler mAICloudServeHandler; // 云端任务
private BaseAIDialHandler mAIDialHandler; // AI 表盘对话任务
private TransferWaitingDialog waitingDialog;//断开的时候要更新
private boolean isTransferring = false;
private boolean mIsAIDialRunning = false;
...
}
Source: AIManager.java
字段分四类,清晰映射到四条职责线:
| 字段组 | 字段 | 职责线 |
|---|---|---|
| 讯飞 AI 能力 | mIflytekChatWrapper / mIflytekTtsWrapper / mIflytekIatWrapper | 听 / 想 / 说三条 AI 管线 |
| RCSP 设备通道 | mAIRecordWrapper / mAICloudServeWrapper / mAIDialWrapper | 与手表的蓝牙数据交换 |
| 任务处理器 | mAIIatHandler / mAICloudServeHandler / mAIDialHandler | 各业务域的处理逻辑 |
| 状态与 UI | waitingDialog / isTransferring / mIsAIDialRunning | 传输等待弹窗与 AI 表盘运行状态 |
设计意图:mIsAIDialRunning 与 isTransferring 两个布尔状态是并发防护的关键——isTransferring 标记缩略图/表盘文件传输中,避免与 AI 对话流程互相打断;mIsAIDialRunning 标记 AI 表盘会话是否激活,控制录音处理开关。
AI 表盘状态机(AIDialListener)
AIManager 内部通过匿名内部类 AIDialListener 监听设备端 AI 表盘界面状态变化,这是整个语音助手的核心驱动事件:
private final AIDialListener mAIDialListener = new AIDialListener() {
@Override
public void onDevNotifyAIDialUIChange(int state) {
super.onDevNotifyAIDialUIChange(state);
if (state == 0) {//退出AI表盘界面
JL_Log.d(TAG, "onDevNotifyAIDialUIChange", "退出AI表盘界面");
mAIRecordWrapper.stopHandleRecord();//取消处理AI录音数据
if (waitingDialog != null && !isTransferring) {
waitingDialog.dismiss();
}
mIsAIDialRunning = false;
} else if (state == 1) {//进入AI表盘界面
JL_Log.d(TAG, "onDevNotifyAIDialUIChange", "进入AI表盘界面");
mAIRecordWrapper.startHandleRecord();//开始处理AI录音数据
mAIIatHandler.setAIChatHandler(mAIDialHandler);
mIsAIDialRunning = true;
if (waitingDialog == null) {
waitingDialog = new TransferWaitingDialog();
}
if (!waitingDialog.isShow() && !waitingDialog.isAdded()) {
AppCompatActivity appCompatActivity = (AppCompatActivity) ActivityManager.getInstance().getCurrentActivity();
FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
waitingDialog.show(fragmentManager, waitingDialog.getClass().getCanonicalName());
}
}
}
...
};
Source: AIManager.java
关键行为拆解:
state == 1(进入 AI 表盘):调用mAIRecordWrapper.startHandleRecord()开始处理录音数据;调用mAIIatHandler.setAIChatHandler(mAIDialHandler)将识别结果动态路由到 AI 表盘对话处理器——这是识别与对话解耦的挂接点;随后弹出TransferWaitingDialog等待弹窗(复用ActivityManager获取当前 Activity 与 FragmentManager)。state == 0(退出 AI 表盘):stopHandleRecord()停止录音处理,条件性地关闭弹窗(!isTransferring保证传输进行中不打断),并将mIsAIDialRunning置回false。
同监听器还处理传输与安装事件:
@Override
public void onTransferThumbStart() {
super.onTransferThumbStart();
isTransferring = true;
if (waitingDialog != null) {
waitingDialog.updateText(mContext.getString(R.string.transfer_ing));
}
}
@Override
public void onTransferThumbFinish(boolean isSuccess) {
super.onTransferThumbFinish(isSuccess);
isTransferring = false;
if (waitingDialog != null) {
// waitingDialog.updateText("AI表盘对话中...");
}
}
@Override
public void onInstallDialStart() {
super.onInstallDialStart();
isTransferring = true;
if (waitingDialog != null) {
waitingDialog.updateText(mContext.getString(R.string.transfer_ing));
}
}
@Override
public void onInstallDialFinish(boolean isSuccess) {
super.onInstallDialFinish(isSuccess);
isTransferring = false;
if (waitingDialog != null) {
// waitingDialog.updateText("AI表盘对话中...");
}
}
Source: AIManager.java
设计意图:表盘缩略图(Thumb)与表盘安装(Install Dial)是耗时传输操作,期间 UI 文案更新为 R.string.transfer_ing("传输中"),并用 isTransferring 标志防止传输期间 AI 会话弹窗被误关闭——这是典型的异步任务互斥保护。
BaseAIHandler —— 任务基类契约
所有 AI 任务处理器继承自抽象基类 BaseAIHandler,定义了两项核心契约:
public abstract class BaseAIHandler {
protected final String TAG = this.getClass().getSimpleName();
protected WatchManager mRcspOp;
protected Context mContext;
public BaseAIHandler(WatchManager rcspOp, Context context) {
mRcspOp = rcspOp;
mContext = context;
}
public void release() {
}
protected boolean isConnected() {
return mRcspOp.isConnected();
}
}
Source: BaseAIHandler.java
- 构造注入:统一注入
WatchManager(RCSP 蓝牙操作对象)与Context,保证所有子类都能访问设备通道; release():默认为空实现,子类按需覆写释放 AI 资源(如取消识别、断开会话)——这是生命周期管理的扩展点;isConnected():委托给WatchManager.isConnected(),子类在执行 AI 任务前可用它做连接前置校验,避免蓝牙断开时误操作。
Handler 派生体系
从 BaseAIHandler 派生出四条业务线(位于 tool/aiui/handle/ 包):
| 抽象基类 | 讯飞实现类 | 职责 |
|---|---|---|
BaseAIIatHandler | IflytekAIIatHandler | 语音识别(IAT),将录音流转换为文本;通过 setAIChatHandler(...) 支持把识别结果交给不同的对话处理器 |
BaseAIChatHandler | (供 Dial/Cloud 复用) | AI 对话通用逻辑,定义聊天请求的公共处理流程 |
BaseAIDialHandler | IflytekAIDialHandler | AI 表盘场景对话:接收 IAT 文本 → 调用星火大模型 → 返回回答 |
BaseAICloudServeHandler | IflytekAICloudServeHandler | 云端服务:与 AICloudServeWrapper 协同处理手表侧发起的云端功能请求 |
设计意图:BaseAIIatHandler.setAIChatHandler(...) 是"识别结果路由器"——同一套录音识别管线可把文本喂给不同下游(AI 表盘对话或普通聊天),无需复制识别逻辑;这正是 AIManager 在 state == 1 时调用 mAIIatHandler.setAIChatHandler(mAIDialHandler) 的原因。
Core Flow:AI 表盘语音对话全流程
以下时序图展示了从手表端进入 AI 表盘到语音回答回传的完整端到端流程:
sequenceDiagram
participant Watch as 智能手表 (AI 表盘)
participant RCSP as RCSP 通道 (AIDialWrapper/AIRecordWrapper)
participant AM as AIManager
participant IAT as BaseAIIatHandler/IflytekIatWrapper
participant CHAT as IflytekChatWrapper (星火大模型)
participant TTS as IflytekTtsWrapper
participant DIAL as BaseAIDialHandler
Watch->>RCSP: 进入 AI 表盘 (通知 state=1)
RCSP->>AM: onDevNotifyAIDialUIChange(1)
AM->>AM: startHandleRecord() + setAIChatHandler(mAIDialHandler)
AM->>AM: 弹出 TransferWaitingDialog
Watch->>RCSP: 录音数据流 (BLE)
RCSP->>IAT: 语音数据 (AIRecordWrapper)
IAT->>IAT: ASR 识别为文本
IAT->>DIAL: 文本 (setAIChatHandler 路由)
DIAL->>CHAT: 请求回答
CHAT->>CHAT: 星火大模型生成回答
CHAT-->>DIAL: 回答文本
DIAL->>TTS: 合成语音
TTS->>RCSP: 语音数据 (AIDialWrapper)
RCSP->>Watch: RCSP 回传语音播放
Watch->>RCSP: 退出 AI 表盘 (通知 state=0)
RCSP->>AM: onDevNotifyAIDialUIChange(0)
AM->>AM: stopHandleRecord() + 关闭弹窗
步骤分解
- 进入会话:手表端切换至 AI 表盘界面,通过 RCSP 通知手机端
state=1;AIManager的AIDialListener收到事件后开启录音处理管线,并将 IAT 输出路由到AIDialHandler,同时展示"等待/传输中"弹窗; - 语音上行:手表采集用户语音,
AIRecordWrapper通过蓝牙持续接收录音数据; - 识别:
IflytekIatWrapper(讯飞 IAT/ASR)将录音转写为文本; - 对话:文本经
setAIChatHandler挂接的BaseAIDialHandler送入IflytekChatWrapper(基于 SparkChain 的星火大模型)生成回答; - 合成与回传:回答文本由
IflytekTtsWrapper合成为语音,经AIDialWrapper通过 RCSP 回传手表播放; - 退出会话:手表退出 AI 表盘(
state=0),AIManager停止录音处理、条件性关闭弹窗,重置mIsAIDialRunning。
注:上述第 2-5 步的调用链由
AIManager各字段装配关系与AIDialListener行为推导,各 Wrapper 内部与讯飞 SDK 交互的细节需结合对应文件进一步确认。
讯飞封装层(iflytek 包)
tool/aiui/iflytek/ 包封装了讯飞三件套与表盘风格助手,是子系统的"AI 引擎室":
| 类 | 封装的 AI 能力 | 底层 SDK | 用途 |
|---|---|---|---|
IflytekIatWrapper | 语音识别(IAT/ASR) | 讯飞语音听写 | 将手表录音转文本 |
IflytekChatWrapper | 大模型对话 | 讯飞星火 SparkChain | 生成健康问答回答 |
IflytekTtsWrapper | 语音合成(TTS) | 讯飞语音合成 | 将回答文本转语音 |
IflytekAIDialStyleHelper | AI 表盘风格初始化 | AIUI 配置 | 加载 aiui_phone.cfg,配置表盘 AI 风格 |
初始化入口
HealthApplication.onCreate() 在应用启动阶段完成 AI 表盘风格助手的初始化,与 CustomDialManager.init(this) 等初始化并列执行:
CustomDialManager.init(this);
IflytekAIDialStyleHelper.init(this);
BaseUnitConverter.setType(ConfigHelper.getInstance().getUnitType());
Source: HealthApplication.java
设计意图:AI 能力采用"启动时静态初始化 + 使用时门面注入"的两段式生命周期——IflytekAIDialStyleHelper.init(this) 在 Application 中尽早完成 AIUI 配置装载(对应资源 assets/cfg/aiui_phone.cfg 与 libs/SparkChain_V2.0.1_rc1.aar),确保后续 AIManager 创建 Wrapper 时可立即使用,避免首帧对话卡顿。
RCSP 通道封装层(rcsp 包)
tool/aiui/rcsp/ 包负责与手表侧的协议交互:
| 类 | 方向 | 职责 |
|---|---|---|
AIRecordWrapper | 上行 | 接收/处理手表端 AI 录音数据,startHandleRecord() / stopHandleRecord() 控制处理开关 |
AIDialWrapper + AIDialListener | 双向 | AI 表盘通道:上报表盘 UI 状态(onDevNotifyAIDialUIChange)、缩略图传输(onTransferThumbStart/Finish)、表盘安装(onInstallDialStart/Finish)、语音回传 |
AICloudServeWrapper + AICloudServeWrapperListener | 双向 | 云端服务通道:承载手表侧发起的云端功能请求/响应 |
设计意图:RCSP 层与讯飞层严格隔离。协议报文解析(RCSP 命令)只存在于 rcsp 包,AI 业务逻辑只存在于 handle 包,二者通过 AIManager 与 WatchManager(RCSP 操作入口)衔接,这样讯飞 SDK 升级或 RCSP 协议变更不会互相波及。
数据模型与持久化
AI 云端服务消息通过本地数据库持久化:
erDiagram
AICloudMessageEntity {
string id PK
string message
int type
long timestamp
}
AICloudMessageEntity(com.jieli.healthaide.data.entity):云端 AI 消息实体,作为AICloudServeHandler/AICloudServeWrapper与本地存储之间的数据载体;AICloudMessageDao(com.jieli.healthaide.data.dao):基于 Room 的 DAO 接口,提供云端消息的增删改查能力。
设计意图:云端服务消息落库的意义在于断连续传与历史追溯——蓝牙连接不稳定时,未完成的消息可保留在本地,重连后由 Handler 层继续处理;同时用户可回看历史 AI 问答记录。实体字段的具体定义需查阅 AICloudMessageEntity.java 确认。
资源与依赖
| 资源 | 路径 | 说明 |
|---|---|---|
| AIUI 配置 | app/src/main/assets/cfg/aiui_phone.cfg | 讯飞 AIUI 手机端配置文件,被 IflytekAIDialStyleHelper 加载 |
| SparkChain SDK | app/libs/SparkChain_V2.0.1_rc1.aar | 讯飞星火大模型 Android SDK,IflytekChatWrapper 的底层依赖 |
配置选项
AI 语音助手的能力开关与行为由代码常量、AIUI 配置与 SDK 初始化共同决定,主要可配置项如下:
| 配置项 | 类型 | 默认值 | 位置 | 说明 |
|---|---|---|---|---|
aiui_phone.cfg | 文件 | assets/cfg/aiui_phone.cfg | 资源目录 | 讯飞 AIUI 手机端配置(唤醒词、识别参数等),由 IflytekAIDialStyleHelper.init() 加载 |
| SparkChain SDK 版本 | AAR | SparkChain_V2.0.1_rc1.aar | app/libs/ | 星火大模型对话能力版本 |
R.string.transfer_ing | 字符串资源 | "传输中…" | res/values/strings.xml | 缩略图/表盘传输等待文案 |
state 表盘状态值 | int | 0=退出,1=进入 | 设备固件协议 | 触发 onDevNotifyAIDialUIChange 的状态语义 |
说明:
AIManager及各 Handler 未暴露动态参数化配置(未发现 SharedPreferences/ConfigHelper 中对 AI 行为的开关项);AI 具体识别/合成参数均内嵌于讯飞 Wrapper 与 cfg 文件中,具体键值需查阅 aiui_phone.cfg 与对应 Wrapper 源码。
API Reference
AIManager(门面类)
| 成员 | 类型 | 说明 |
|---|---|---|
mAIDialListener | AIDialListener | 设备 AI 表盘状态/传输/安装事件监听,驱动录音管线开关与弹窗管理 |
mAICloudServeWrapperListener | AICloudServeWrapperListener | 云端服务响应监听 |
mAIIatHandler.setAIChatHandler(handler) | BaseAIIatHandler 方法 | 设置识别文本的下游对话处理器(运行时路由) |
BaseAIHandler(抽象基类)
public BaseAIHandler(WatchManager rcspOp, Context context)
- 参数:
rcspOp— RCSP 蓝牙操作对象(WatchManager);context— 应用上下文; - 说明:所有 AI 任务处理器的统一构造入口,注入设备通道与上下文。
public void release()
- 说明:释放 AI 资源,默认空实现,子类覆写。在关闭 AI 会话/退出页面时调用。
protected boolean isConnected()
- 返回:
mRcspOp.isConnected()的结果; - 用途:任务执行前的连接前置校验,避免蓝牙断开时向设备发送无效请求。
AIDialListener(接口回调)
| 回调 | 参数 | 触发时机 |
|---|---|---|
onDevNotifyAIDialUIChange(int state) | 0=退出 AI 表盘,1=进入 | 手表端 AI 表盘界面切换 |
onTransferThumbStart() | — | 表盘缩略图开始传输 |
onTransferThumbFinish(boolean isSuccess) | 是否成功 | 表盘缩略图传输结束 |
onInstallDialStart() | — | 表盘安装开始 |
onInstallDialFinish(boolean isSuccess) | 是否成功 | 表盘安装结束 |
Failure Modes、边界情况与并发
连接状态异常
BaseAIHandler.isConnected() 提供统一连接检查,但若在蓝牙断开瞬间发起 AI 请求,AIDialWrapper/AIRecordWrapper 的 RCSP 发送会失败。代码中未见显式重试机制——失败处理依赖 RCSP 层的错误回调(JL_Log 日志体系)与上层 TransferWaitingDialog 的状态提示,属于"快速失败 + 用户可见反馈"的策略。
AI 表盘状态与传输互斥
AIManager 用两个布尔状态处理并发:
isTransferring:缩略图/表盘安装传输期间置true,此时即使收到state=0退出事件也不会 dismiss 等待弹窗(if (waitingDialog != null && !isTransferring)),防止"退出弹窗打断传输"的竞态;mIsAIDialRunning:标记 AI 表盘会话激活,控制录音处理开关与弹窗展示,避免重复 show 弹窗(!waitingDialog.isShow() && !waitingDialog.isAdded()双保险)。
弹窗生命周期风险
TransferWaitingDialog 通过 FragmentManager.show() 展示,若宿主 Activity 在弹窗展示期间被销毁(如用户按 Home 或旋转屏幕),可能存在 Fragment 状态丢失风险——代码通过 isAdded()/isShow() 双重判断降低重复添加异常(IllegalStateException)的概率。
语音数据边界
手表录音为持续数据流,若用户长时间说话或录音包过大,AIRecordWrapper 的内存与蓝牙带宽压力上升;退出表盘时 stopHandleRecord() 必须及时调用以释放资源——该调用在 onDevNotifyAIDialUIChange(0) 中同步执行,保证退出即清理。
性能与运维注意
- 链路延迟:一条语音问答的端到端延迟 = 蓝牙上行传输 + IAT 识别 + 星火生成 + TTS 合成 + 蓝牙下行传输,任一环节超时都会放大体感延迟;
TransferWaitingDialog的"传输中"文案即用于掩盖这一异步等待; - AI 资源生命周期:
IflytekChatWrapper/IflytekIatWrapper/IflytekTtsWrapper均在AIManager中长期持有,属于重量级对象,不应在页面级频繁创建销毁,应复用门面实例; - 依赖 AAR 体积:
SparkChain_V2.0.1_rc1.aar为本地依赖,增大 APK 体积,是 AI 能力上手机端的固有成本。
扩展点
- 替换/新增 AI 供应商:实现
BaseAIHandler的新子类(如BaiduAIIatHandler),在AIManager中替换对应字段装配即可,调用方(UI/Service)无感知; - 新增对话下游:
BaseAIIatHandler.setAIChatHandler(...)允许把同一识别管线路由到任意BaseAIChatHandler实现,可扩展"普通聊天""健康咨询"等新场景; - 新增设备侧 AI 功能:仿照
AIDialWrapper模式新增 RCSP 包装器 + 监听器,并在AIManager中装配; - 云端消息扩展:通过
AICloudMessageEntity/AICloudMessageDao扩展消息类型(type字段)实现更多云端 AI 服务。
测试情况
仓库中未发现针对 tool/aiui 包的专项单元测试;相关测试文件(ExampleUnitTest、MessageFormatTest、ReceiveHealthDataCmdTest 等)主要覆盖工具类与数据解析逻辑。AI 语音链路依赖真实讯飞 SDK 与蓝牙设备,通常以真机联调验证,单元测试覆盖有限。
Related Links
- HealthApplication.java(AI 初始化入口)
- AIManager.java(AI 管理门面)
- BaseAIHandler.java(任务基类)
- AICloudMessageEntity.java(云端消息实体)
- AICloudMessageDao.java(云端消息 DAO)
- aiui_phone.cfg(AIUI 配置)
- 相关相邻主题:RCSP 蓝牙通信(WatchManager)、健康数据采集、App 启动流程(HealthApplication)