发送接口参考
本文档是 JieLi_Home_Demo(Flutter-JL_Home 插件)中 Dart 侧“发送(send)”类接口的参考手册,覆盖 BleTransferManager、BleCustomCmdManager、BleAuraCastManager 中所有以 send 开头的方法,以及它们依赖的方法通道常量 BleMethodConstants。
Purpose and Scope
本页回答以下问题:
- 插件提供了哪些"从 App 向 BLE 设备发送命令/数据"的接口?
- 每个
send*方法的签名、参数、返回值与设计意图是什么? - 这些方法是如何统一经过
BleBaseManager.invokeMethod走方法通道(MethodChannel)到达原生层并最终发往设备的?
本页边界: 只覆盖"发送"方向(App → 设备)的 Dart 侧 API 表面。以下主题属于兄弟页面,不在本页展开:
- 设备扫描 / 搜索接口
- 连接与断开管理接口
- OTA 升级接口
- 设备信息查询与事件回调(接收方向,设备 → App)
若目录 10-interface-reference 下存在对应兄弟条目,请以它们为准。
Overview
Flutter-JL_Home 是一个基于杰理(JieLi)BLE 芯片的 Flutter 插件 Demo。插件采用典型的"Dart Manager 类 + 原生实现"分层结构:
flowchart TD
subgraph sg_App["App 业务层 (example)"]
UI["页面 / 业务调用方"]
end
subgraph sg_Dart["Dart 插件层 (lib/manager)"]
Transfer["BleTransferManager"]
Custom["BleCustomCmdManager"]
Aura["BleAuraCastManager"]
Base["BleBaseManager.invokeMethod"]
Consts["BleMethodConstants"]
end
subgraph sg_Channel["平台通道"]
MC["MethodChannel"]
end
subgraph sg_Native["原生层 (Android / iOS)"]
Native["原生实现"]
end
subgraph sg_Device["BLE 设备"]
Dev["杰理 BLE 芯片设备"]
end
UI --> Transfer
UI --> Custom
UI --> Aura
Transfer --> Base
Custom --> Base
Aura --> Base
Transfer --> Consts
Custom --> Consts
Aura --> Consts
Base --> MC
MC --> Native
Native --> Dev
关键设计点:
- 统一入口:所有
send*方法都调用静态方法BleBaseManager.invokeMethod(...),因此参数校验、通道调用、异常传播集中在BleBaseManager一处,各 Manager 只负责组装"方法名 + 参数 Map"。 - 常量集中管理:方法名字符串(如
"sendCustomCommand"、"sendRecordIndex")与参数键(如argCustomData、argRecordIndex)都定义在BleMethodConstants中,避免魔法字符串散落各处,也便于原生侧与 Dart 侧对齐。 - 返回值约定:大部分发送接口返回
Future<void>(异步执行、不关心结果,属"发后即忘");BleAuraCastManager.sendAuraCastSwitchState返回Future<bool>,用于让调用方感知开关状态是否发送成功。 - 静态方法风格:三个 Manager 均为纯静态工具类风格,无需实例化,业务层直接
BleTransferManager.sendXxx(...)调用,使用简单。
发送接口总览
已从源码中确认的 send* 方法如下:
| Manager 类 | 方法 | 签名(已核实) | 用途 |
|---|---|---|---|
BleTransferManager | sendAudioState | Future<void> sendAudioState(RecordWay recordWay) | 发送音频状态(录音方式) |
BleTransferManager | sendRecordIndex | Future<void> sendRecordIndex(int recordIndex) | 发送录音会话索引 |
BleTransferManager | sendFaceToFaceProgress | Future<void> sendFaceToFaceProgress(int progress) | 发送面对面翻译进度 |
BleTransferManager | sendSimultaneousMuteEvent | Future<void> sendSimultaneousMuteEvent() | 发送同传静音事件 |
BleTransferManager | sendSimultaneousPlayState | Future<void> sendSimultaneousPlayState() | 发送同传播放状态 |
BleCustomCmdManager | sendCustomCommand | Future<void> sendCustomCommand(Uint8List data) | 发送自定义命令(原始字节) |
BleAuraCastManager | sendAuraCastSwitchState | Future<bool> sendAuraCastSwitchState(bool state) | 发送 AuraCast 开关状态 |
所有方法内部均以 BleBaseManager.invokeMethod(...) 为出口(见下文"核心流程")。
主内容:各 Manager 发送接口详解
BleTransferManager —— 传输与翻译相关发送接口
BleTransferManager 位于 code/JieLi_Home_Demo/lib/manager/ble_transfer_manager.dart,集中了与"传输、录音、翻译"场景相关的发送方法。从源码中确认的方法与行号如下:
sendAudioState(RecordWay recordWay)(L93):向设备上报当前的录音方式/音频状态。参数RecordWay是枚举类型,表示录音通路(例如设备麦克风/手机麦克风等,具体枚举值定义位置未在本页核实)。当 App 侧录音方式切换时调用,让设备端同步状态。sendRecordIndex(int recordIndex)(L100-L103):发送当前录音会话的索引。App 每开始/切换一段录音会话时把索引值同步给设备,设备据此区分不同的录音文件。sendFaceToFaceProgress(int progress)(L113-L114):发送面对面翻译的进度值,用于设备端展示进度。sendSimultaneousMuteEvent()(L120-L121):发送同声传译的静音事件,通知设备进入/退出静音(具体状态由设备侧协议决定)。sendSimultaneousPlayState()(L132-L133):发送同声传译的播放状态,让设备同步播放/暂停等状态。
这些方法全部返回 Future<void>,属于"发后即忘"型接口:调用方只关心命令是否已投递到通道,不等待设备侧的业务应答。它们的共同模式是:
static Future<void> sendRecordIndex(int recordIndex) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodSendRecordIndex,
arguments: {BleMethodConstants.argRecordIndex: recordIndex},
// ...(其余参数与方法体结尾未在本页展开)
);
}
Source: ble_transfer_manager.dart
设计意图:把"设备端需要知道的状态变化"建模成独立的小方法,语义清晰、调用点直观;同时把通道细节下沉到 BleBaseManager,业务代码无需关心 MethodChannel 的实现差异。
BleCustomCmdManager —— 自定义命令发送
BleCustomCmdManager 位于 code/JieLi_Home_Demo/lib/manager/ble_custom_cmd_manager.dart,提供向设备发送"任意原始字节"的通用出口,是协议扩展的兜底接口:
class BleCustomCmdManager {
static Future<void> sendCustomCommand(Uint8List data) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodSendCustomCommand,
arguments: {BleMethodConstants.argCustomData: data},
// ...(其余参数与方法体结尾未在本页展开)
);
}
}
Source: ble_custom_cmd_manager.dart
参数 Uint8List data 是待发送的原始字节流。为什么需要它:上面 BleTransferManager 的专用方法只能表达固定业务,而厂商自定义协议、调试命令、新功能联调等场景需要把未封装的字节直接发给设备。sendCustomCommand 就是这个"逃生舱",让上层在不动插件代码的情况下扩展指令集。
BleAuraCastManager —— AuraCast 开关发送
BleAuraCastManager 位于 code/JieLi_Home_Demo/lib/manager/ble_aura_cast_manager.dart,管理 AuraCast(音频投送)相关能力,其中发送类接口为:
static Future<bool> sendAuraCastSwitchState(bool state) async {
return await BleBaseManager.invokeMethod(
// ...(方法名与参数未在本页展开)
);
}
Source: ble_aura_cast_manager.dart
与 Future<void> 接口不同,它返回 Future<bool>,即把原生侧的调用结果(成功/失败)透传给调用方,适合需要 UI 反馈的场景(如开关切换后提示失败)。
BleMethodConstants —— 通道方法名与参数键常量
BleMethodConstants 位于 code/JieLi_Home_Demo/lib/constant/ble_method_constants.dart,是 Dart 侧与原生侧约定的"协议字典"。本页已核实的两条发送相关常量:
/// 发送自定义命令
static const String methodSendCustomCommand = "sendCustomCommand";
Source: ble_method_constants.dart
/// 发送录音会话的索引
static const String methodSendRecordIndex = "sendRecordIndex";
Source: ble_method_constants.dart
从 grep 结果还可确认参数键常量 argCustomData(配合 methodSendCustomCommand)与 argRecordIndex(配合 methodSendRecordIndex)存在。其余发送方法的常量(如音频状态、进度、同传事件、AuraCast 开关等)也定义在同一文件中,具体命名与取值未在本页逐条核实,可打开该文件按 method 前缀检索。
核心流程
所有发送接口共享同一条调用链。以 sendCustomCommand 为例:
sequenceDiagram
participant App as 业务调用方
participant Mgr as BleCustomCmdManager
participant Base as BleBaseManager
participant MC as MethodChannel
participant Native as 原生实现
participant Dev as BLE 设备
App->>Mgr: sendCustomCommand(data)
Mgr->>Base: invokeMethod("sendCustomCommand", {customData: data})
Base->>MC: invokeMethod(method, arguments)
MC->>Native: 平台方法调用
Native->>Dev: 通过 BLE 写入数据
Dev-->>Native: 设备应答(可选)
Native-->>MC: result
MC-->>Base: Future 结果
Base-->>Mgr: 完成 / 异常
Mgr-->>App: Future<void> 完成 / PlatformException
步骤说明:
- 业务层调用:页面或状态管理器直接调用静态方法,如
BleCustomCmdManager.sendCustomCommand(bytes)。 - 组装参数:Manager 把方法名(
BleMethodConstants.methodSendCustomCommand)和参数 Map({BleMethodConstants.argCustomData: data})传给BleBaseManager.invokeMethod。 - 通道转发:
BleBaseManager通过 MethodChannel 把(method, arguments)投递到原生侧(BleBaseManager.invokeMethod的具体实现、通道名与参数校验逻辑未在本页读取,可查看lib/manager下的基类文件)。 - 原生执行:Android/iOS 原生实现解析方法名与参数,经 BLE 协议栈把数据写入设备。
- 结果回流:原生侧返回结果(或抛出
PlatformException),最终以Future形式回到调用方。
为什么统一走 MethodChannel 而不是直接维护 Socket? 因为 Flutter 插件与原生层之间天然存在隔离,MethodChannel 是官方推荐的异步通信机制:Dart 侧拿到 Future、原生侧拿到回调,错误可以双向传播。各 Manager 只做"语义封装",底层统一由 BleBaseManager 处理通道生命周期,避免每个方法重复样板代码。
使用示例
以下示例均提取自已核实的源码片段,展示了各 Manager 的调用方式。
示例 1:发送自定义命令(原始字节)
// 组装要下发的原始字节(例如厂商自定义协议帧)
Uint8List data = Uint8List.fromList([0x01, 0x02, 0x03]);
await BleCustomCmdManager.sendCustomCommand(data);
实现本身(已核实):
static Future<void> sendCustomCommand(Uint8List data) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodSendCustomCommand,
arguments: {BleMethodConstants.argCustomData: data},
);
}
Source: ble_custom_cmd_manager.dart
示例 2:发送录音会话索引
static Future<void> sendRecordIndex(int recordIndex) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodSendRecordIndex,
arguments: {BleMethodConstants.argRecordIndex: recordIndex},
);
}
Source: ble_transfer_manager.dart
示例 3:发送音频状态与翻译/同传状态
// 录音方式变化时上报设备
await BleTransferManager.sendAudioState(RecordWay.xxx);
// 面对面翻译进度
await BleTransferManager.sendFaceToFaceProgress(progress);
// 同传静音事件 / 播放状态
await BleTransferManager.sendSimultaneousMuteEvent();
await BleTransferManager.sendSimultaneousPlayState();
Sources:
示例 4:AuraCast 开关(返回结果)
bool ok = await BleAuraCastManager.sendAuraCastSwitchState(isOn);
if (!ok) {
// 提示用户开关操作未成功
}
Source: ble_aura_cast_manager.dart
示例 5:在业务代码中调用(参考 example 工程风格)
example 工程中的页面 Manager(如 face_to_face_manager.dart、setting_manager.dart、translate_page_manager.dart)是这些发送接口的典型调用方:在按钮回调或状态变更时调用对应 send* 方法,把用户操作同步给设备。
API Reference
以下为已从源码核实的发送接口签名。BleBaseManager.invokeMethod 为各方法的公共出口,其完整实现(通道名、错误包装等)未在本页读取。
BleTransferManager.sendAudioState(RecordWay recordWay): Future<void>
向设备上报当前音频/录音状态。
参数:
recordWay(RecordWay):录音方式枚举。具体枚举值定义位置未在本页核实,可检索RecordWay定义。
返回: Future<void>,通道调用完成后完成;失败时抛出平台异常。
BleTransferManager.sendRecordIndex(int recordIndex): Future<void>
发送当前录音会话索引(方法名常量 methodSendRecordIndex,参数键 argRecordIndex)。
参数:
recordIndex(int):录音会话索引。
返回: Future<void>。
BleTransferManager.sendFaceToFaceProgress(int progress): Future<void>
发送面对面翻译进度。
参数:
progress(int):进度值(0-100 之类的量纲由设备协议约定)。
返回: Future<void>。
BleTransferManager.sendSimultaneousMuteEvent(): Future<void>
发送同声传译静音事件(无参数)。
BleTransferManager.sendSimultaneousPlayState(): Future<void>
发送同声传译播放状态(无参数)。
BleCustomCmdManager.sendCustomCommand(Uint8List data): Future<void>
向设备发送自定义原始字节命令(方法名常量 methodSendCustomCommand,参数键 argCustomData)。
参数:
data(Uint8List):待发送的原始字节。
返回: Future<void>。
注意: 字节长度与 MTU / 分包策略由原生层与设备协议决定,超长数据需自行在协议层处理。
BleAuraCastManager.sendAuraCastSwitchState(bool state): Future<bool>
发送 AuraCast 开关状态,并返回原生侧执行结果。
参数:
state(bool):目标开关状态。
返回: Future<bool>,true 表示发送成功,false 表示失败。
公共出口:BleBaseManager.invokeMethod(...)
所有 send* 方法最终调用 BleBaseManager.invokeMethod(method, arguments: ...)。该静态方法负责:
- 接收方法名字符串与参数 Map;
- 通过 MethodChannel 与原生层通信;
- 把结果/异常以
Future形式返回给调用方。
实现细节(通道名、错误类型包装、超时处理等)未在本页读取,如需深入请查看
lib/manager下的BleBaseManager源码。
通道常量配置
方法名字符串与参数键集中在 BleMethodConstants(code/JieLi_Home_Demo/lib/constant/ble_method_constants.dart),Dart 侧与原生侧共用同一套命名。本页已核实的发送相关常量:
| 常量 | 值(已核实) | 关联接口 | 说明 |
|---|---|---|---|
methodSendCustomCommand | "sendCustomCommand" | BleCustomCmdManager.sendCustomCommand | 发送自定义命令 |
argCustomData | 参数键(已确认存在) | 同上 | 自定义命令字节参数 |
methodSendRecordIndex | "sendRecordIndex" | BleTransferManager.sendRecordIndex | 发送录音会话索引 |
argRecordIndex | 参数键(已确认存在) | 同上 | 录音索引参数 |
其余 send* 方法(sendAudioState、sendFaceToFaceProgress、sendSimultaneousMuteEvent、sendSimultaneousPlayState、sendAuraCastSwitchState)对应的方法名常量也定义在同一文件中,遵循 methodSendXxx = "sendXxx" 的命名规律,可在该文件中按 method 前缀检索确认。
设计意图: 常量集中管理避免了 Dart 侧与原生侧因字符串拼写不一致导致的静默失败,且 IDE 可以对常量做引用跳转与重命名重构。
失败模式、边界情况与并发
以下结论来自对本页已核实代码的分析;凡是超出已读源码范围的判断均明确标注。
失败模式
- 平台异常传播:
send*方法内部直接await BleBaseManager.invokeMethod(...),原生侧抛出的异常(典型如PlatformException,表示原生实现/设备返回错误)会沿Future链传播到调用方。调用方应使用try/catch包裹,否则会形成未捕获异常。 - 缺少原生实现:若原生侧未注册对应方法(例如只集成了 Android 插件而运行在 iOS 上),MethodChannel 会抛出
MissingPluginException——这是所有通过invokeMethod调用的接口共有的风险。 - 设备离线/断连:
Future<void>接口本身不承载"设备是否真正收到"的信息。若设备已断开,错误发生在原生 BLE 写入阶段,仍以异常形式冒泡。需要强确认的场景(如 AuraCast 开关)应使用返回Future<bool>的sendAuraCastSwitchState。
边界情况
Uint8List长度:sendCustomCommand接受任意长度字节,但 BLE 单包 MTU 有限;超长数据需要原生层分包或由调用方自行拆分(分包策略未在本页核实)。Future<void>的语义:完成仅代表"已投递到通道",不代表"设备已处理"。对时序敏感的业务需依赖设备侧的回调接口(见"相关链接"中接收方向接口)。RecordWay枚举:sendAudioState的参数类型为枚举,调用前需确认取值与设备协议一致(枚举定义位置未在本页核实)。
并发
所有 send* 方法均为静态方法、无共享可变状态,天然线程安全。但多个发送操作并发执行时,命令到达设备的顺序取决于 MethodChannel 与原生队列的调度顺序,不保证 FIFO;对顺序敏感的命令序列建议调用方串行等待(await 逐个发送)。
性能与运维注意
- 调用频率:发送接口属于轻量封装,单次开销主要是 MethodChannel 往返。避免在 UI 帧内高频循环调用(如进度值每帧上报),建议节流(throttle)后发送。
- 日志与排查:方法名常量集中在
BleMethodConstants,排查问题时可按"send*"关键字在 Dart 侧与原生侧同时检索,快速定位协议对齐点。 - 扩展新指令:新增发送能力时,按现有模式复制即可——在
BleMethodConstants增加methodSendXxx与参数键,在对应 Manager 增加静态方法,原生侧注册同名方法。
扩展点
- 新增发送方法:遵循"常量 + Manager 静态方法 + invokeMethod"三步模式,与现有实现风格保持一致。
- 通用兜底通道:
sendCustomCommand(Uint8List)允许不修改插件即可下发任意协议字节,是协议扩展的首选入口。 - 返回结果语义:若新接口需要调用方感知结果,参考
sendAuraCastSwitchState返回Future<bool>;若无需感知,使用Future<void>。 - 接收方向:发送后的设备应答通常通过事件回调通道返回 App(EventChannel/回调接口),属于"接收接口"兄弟页面的范畴,扩展发送能力时应同步设计应答协议。
Related Links
- ble_transfer_manager.dart — 传输/录音/翻译类发送接口
- ble_custom_cmd_manager.dart — 自定义命令发送接口
- ble_aura_cast_manager.dart — AuraCast 开关发送接口
- ble_method_constants.dart — 方法名与参数键常量字典
- 兄弟页面指引:设备扫描/搜索、连接管理、OTA 升级、设备信息查询与事件回调(接收方向)等接口,请参见
10-interface-reference目录下的对应条目。