接收接口与事件参考
本文档是 JieLi Home Flutter 插件(jl_home)的接收侧接口与事件参考,覆盖从 Android 原生层经 EventChannel 推送事件,到 BleEventStream 类型化 Stream 供业务层订阅的完整接收链路。
Purpose and Scope
本页聚焦于接收方向的事件流:即设备/原生层 → Flutter 插件 → 应用订阅者这一方向的所有接口与事件类型。具体包括:
BleBaseEventProcessor的事件通道建立、事件解析与错误处理机制BleEventStream统一门面对外暴露的全部类型化 Stream- 16 个功能 Processor 的事件分类、分发逻辑与承载的数据模型
- 事件的结构(
type/value/data)、订阅方式与典型使用流程
本页不覆盖:向原生侧/设备发送指令的发送接口(方法调用通道,如 ble_method_constants.dart 中定义的方法常量,属于独立的"发送接口与方法参考"页面);各功能(OTA、翻译、EQ 等)的业务逻辑细节见各自功能页面。
Overview
该插件采用 Flutter 标准的 EventChannel 机制实现"原生 → Flutter"的单向事件推送。Android 原生端在蓝牙事件(设备连接、扫描、OTA 进度、音乐信息、音量变化等)发生时,将事件包装成 Map(包含 type、value、data 等键)通过名为 com.jieli.home_plugin/events 的事件通道广播;Dart 侧由 BleBaseEventProcessor 持有唯一的 receiveBroadcastStream() 广播流,各功能 Processor 通过 filterByType() 按 type 过滤出自己关心的事件子集,解析为强类型模型后,经 BleEventStream 的静态属性暴露给业务层。
设计上有三个关键决策:
- 单一通道 + 类型过滤:所有事件共享一个 EventChannel 与一个底层广播流,由
type键区分事件种类,避免为每个功能创建独立通道,减少了原生侧与 Dart 侧的通道管理与内存开销。 - 门面模式(Facade):
BleEventStream以静态 getter 形式聚合全部 Stream,业务代码只需BleEventStream.xxxStream即可订阅,无需关心底层 Processor 的存在。 - 懒加载单例:底层广播流通过
??=惰性初始化,仅在第一次被访问时才建立与原生侧的连接。
Architecture
flowchart TD
subgraph sg_Native["Android 原生层"]
Native["BLE 设备事件源<br/>(连接/扫描/OTA/音乐/音量等)"]
end
subgraph sg_Plugin["Flutter 插件层 jl_home"]
Base["BleBaseEventProcessor<br/>EventChannel('com.jieli.home_plugin/events')"]
Procs["功能 Processor 组<br/>BleDeviceConnectionProcessor / BleOtaProcessor<br/>BleAudioProcessor / BleTransferProcessor / ..."]
Facade["BleEventStream<br/>静态 Stream 门面"]
end
subgraph sg_App["应用层"]
UI["页面 / ViewModel / Manager"]
end
Native -->|"原生事件回调"| Base
Base -->|"receiveBroadcastStream() 广播流"| Procs
Procs -->|"filterByType 过滤 + 模型解析"| Facade
Facade -->|"类型化 Stream 订阅"| UI
架构说明:
- BleBaseEventProcessor 是接收链路的唯一入口:持有
EventChannel('com.jieli.home_plugin/events')与懒加载的广播流,并提供safeCastMap、filterByType、getValueFromEvent、getDataFromEvent等公共工具,以及独立的errorStream处理PlatformException。 - 功能 Processor 组(
lib/processor/目录下 16 个类)各自持有baseStream.filterByType(某事件类型)得到的事件子流,将其解析为具体模型(如DeviceConnection、MusicInfo、VolumeInfo)后对外暴露。 - BleEventStream 是唯一推荐给业务层使用的门面,全部成员为静态,约 50 个 Stream getter 按功能域分组(扫描/连接、OTA、音频、设备音乐、灯光、EQ、音量、声卡、SPDIF、充电盒、Auracast、传输/翻译等)。
接收机制详解
1. 事件通道的建立(BleBaseEventProcessor)
所有事件的源头是 BleBaseEventProcessor。它通过 EventChannel 与 Android 原生侧约定的通道名 com.jieli.home_plugin/events 建立连接,并采用懒加载单例模式保证底层广播流只创建一次:
class BleBaseEventProcessor {
static const EventChannel _eventChannel = EventChannel('com.jieli.home_plugin/events');
// Singleton pattern: ensure baseStream is only initialized once
static Stream<dynamic>? _baseStream;
/// Public access method for base stream
static Stream<dynamic> get baseStream {
_baseStream ??= _eventChannel.receiveBroadcastStream();
return _baseStream!;
}
...
}
Source: ble_base_event_processor.dart
设计意图:receiveBroadcastStream() 返回的是广播流(broadcast stream),允许多个订阅者同时接收同一份事件;??= 确保无论有多少 Processor 或页面引用 baseStream,与原生侧的事件通道只建立一次,避免重复注册原生监听器导致的资源泄漏与事件重复。
2. 事件结构约定
原生侧推送的事件是 Map 结构,由常量类 BleEventConstants 定义键名:
| 键 | 含义 |
|---|---|
keyType | 事件类型字符串,用于 filterByType 过滤(如设备连接状态、OTA 进度等) |
keyValue | 事件主要负载,通常是嵌套 Map,包含该事件的字段 |
keyData | 附加数据(可选),如自定义命令的原始字节 |
BleBaseEventProcessor 提供了三个解析工具,所有 Processor 均基于它们工作:
/// Safe cast dynamic to Map
static Map<String, dynamic> safeCastMap(dynamic data) {
if (data is Map<String, dynamic>) {
return data;
} else if (data is Map) {
return data.cast<String, dynamic>();
} else {
return {};
}
}
/// Filter stream by event type
static Stream<Map<String, dynamic>> filterByType(String type) {
return baseStream
.where((event) => event is Map && event[BleEventConstants.keyType] == type)
.map((event) => safeCastMap(event));
}
/// Get value from event
static Map<String, dynamic> getValueFromEvent(Map<String, dynamic> event) {
return safeCastMap(event[BleEventConstants.keyValue] ?? {});
}
/// Get data from event
static dynamic getDataFromEvent(Map<String, dynamic> event) {
return event[BleEventConstants.keyData];
}
Source: ble_base_event_processor.dart
要点:
safeCastMap兼容Map<String, dynamic>与未泛型的Map,并对非 Map 数据返回空 Map,避免类型转换异常向订阅者传播。filterByType先用where过滤出keyType匹配的事件,再用safeCastMap归一化为强类型 Map。因为baseStream是广播流,where不会丢失任何事件,各 Processor 之间互不干扰。getValueFromEvent/getDataFromEvent把事件负载的取值逻辑收敛到一处,Processor 只需关心业务字段解析。
3. 错误事件流
接收链路对原生侧上报的错误单独处理。errorStream 专门监听 PlatformException:
/// Error stream
static Stream<Map<String, String>> get errorStream {
return baseStream
.where((event) => event is PlatformException)
.map((event) {
final error = event as PlatformException;
if (error.code == BleEventConstants.error) {
return {
BleEventConstants.keyCode: error.code,
BleEventConstants.keyMessage: error.message ?? 'Unknown log error',
};
}
throw error;
});
}
Source: ble_base_event_processor.dart
设计意图:EventChannel 在原生侧 onError 回调时会以 PlatformException 形式出现在 Dart 流中。errorStream 将其过滤出来并归一化为 {code, message} 结构,应用可统一订阅此流做日志或 Toast 提示;对于 code 不等于 BleEventConstants.error 的异常则原样抛出,保证异常语义不被吞掉。
功能 Processor 清单与事件分类
lib/processor/ 目录下共 16 个功能 Processor,各自订阅 baseStream 中属于自己的事件子集并解析为模型。BleEventStream 通过静态 getter 把它们的 Stream 聚合起来对外发布:
| 功能域 | Processor 类 | 暴露的 Stream(经 BleEventStream) |
|---|---|---|
| 基础 | BleBaseEventProcessor | baseStream、errorStream |
| 扫描/连接 | BleDeviceConnectionProcessor | scanStateStream、scanDeviceListStream、deviceConnectionStream |
| OTA | BleOtaProcessor | otaConnectionStream、otaFileListStream、mandatoryUpgradeStream、otaStateStream |
| 音频 | BleAudioProcessor | lineInStatusStream、id3MusicInfoStream、id3MusicStatusStream、fmInfoStream、musicInfoStream、musicProgressStream |
| 设备音乐 | BleDeviceMusicProcessor | storageStatusStream、deviceMusicTabTitleStream、deviceMusicItemModelArrayStream、deviceMusicPlayItemOKStream、deviceMusicLoadFailedStream、deviceMusicCardMessageDismissStream、sdCardStatusStream |
| 灯光 | BleLightProcessor | lightInfoStream |
| EQ | BleEqProcessor | reverberationAllDataStream |
| 音量 | BleVolumeProcessor | volumeInfoStream、volumeCtrlStream |
| 声卡 | BleSoundCardProcessor | soundCardSliderValuesStream、soundCardSelectedStatusStream |
| SPDIF | BleSpdifProcessor | spDifPlayStatus、spDifAudioType |
| PC 从机 | BlePcSlaveProcessor | pcSlavePlayStatus |
| 双设备 | BleDoubleDeviceProcessor | doubleDeviceList |
| 充电盒 | BleChargingCaseProcessor | messagePushStateStream、brightnessStream、resourceListStream、uploadStateStream |
| Auracast | BleAuraCastProcessor | auraScanStateStream、auraBroadcastListStream、auraSyncStateStream、auraConnectFailedStream、auraBroadcastRecordListStream |
| 自定义命令 | BleCustomCmdProcessor | customCommandData(Stream<Uint8List>) |
| 传输/翻译 | BleTransferProcessor | translationModeSuccessStream、workTimeStream、translationModeChangedStream、deviceRecordStateStream、translationRecordStream、simultaneousTranslateResultStream、pcmDataStream、saveSessionRecordSuccessStream、sessionRecordChangedStream、playerStateChangedStream、stateResultChangedStream、recordStateChangedStream 等 |
每个 Stream 的数据类型各不相同:简单状态用 bool/int/String/double,复杂事件用专用模型(如 DeviceConnection、MusicInfo、VolumeInfo、ScanDevice、TranslationRecord、AuraCastBroadcastModel、SoundCardSliderModel、PCSlavePlayStatusInfo、SPDIFPlayStatusInfo 等),传输类事件还有 Uint8List(自定义命令)与 Int16List(PCM 数据)等原始数据流。
BleEventStream 门面
BleEventStream 是插件对外接收接口的唯一推荐入口。它的全部成员都是静态的,命名规则为 功能名 + Stream,便于查找:
/// Bluetooth Feature Plugin Wrapper
///
/// Communicates with the native Android side via 'EventChannel'.
/// All external interfaces are static methods/properties and can be directly accessed through BleEventStream.xxx.
class BleEventStream {
// Core broadcast stream
static Stream<dynamic> get baseStream => BleBaseEventProcessor.baseStream;
...
// Device connection streams
static Stream<DeviceConnection> get deviceConnectionStream =>
BleDeviceConnectionProcessor.deviceConnectionStream;
...
// Get custom data
static Stream<Uint8List> get customCommandData =>
BleCustomCmdProcessor.customCommandData;
...
}
Sources:
设计意图:门面把 16 个 Processor 的 Stream 收拢为一个扁平命名空间,业务层无需 import 任何 Processor 类;同时由于 Stream 类型已经在 getter 上声明(如 Stream<DeviceConnection>),订阅者获得编译期类型安全,减少运行时类型判断。
核心接收流程
从"原生事件发生"到"应用订阅者收到类型化数据"的完整链路如下:
sequenceDiagram
participant N as Android 原生层
participant EC as EventChannel<br/>com.jieli.home_plugin/events
participant BP as BleBaseEventProcessor
participant P as 功能 Processor<br/>(如 BleDeviceConnectionProcessor)
participant S as BleEventStream 门面
participant UI as 应用订阅者<br/>(页面/Manager)
N->>EC: 蓝牙事件回调,发送 {type, value, data}
EC->>BP: 推送到 receiveBroadcastStream()
BP->>BP: 事件是否 PlatformException?
BP-->>BP: 是 → errorStream 归一化为 {code, message}
BP->>P: filterByType(type) 过滤广播流
P->>P: 解析 value → 模型对象<br/>(如 DeviceConnection)
P->>S: 暴露类型化 Stream<T>
S->>UI: onData 推送订阅结果
逐步走读:
- 原生触发:Android 端在 BLE 事件(设备连接状态变化、扫描到新设备、OTA 进度、音乐信息刷新、音量/灯光变化等)发生时,将事件封装为
Map{type, value, data},通过EventChannel的success回调推送。 - 通道接收:
BleBaseEventProcessor.baseStream第一次被访问时调用receiveBroadcastStream()建立广播流,之后原生事件源源不断进入 Dart 侧。 - 类型分发:每个功能 Processor 在初始化时用
filterByType(具体type)订阅广播流,只接收与自己相关的keyType;由于广播流特性,各 Processor 的where过滤互不影响。 - 模型解析:Processor 使用
getValueFromEvent/getDataFromEvent取出负载,构造强类型模型后推送到自己的StreamController。 - 门面发布:
BleEventStream的静态 getter 返回各 Processor 的 Stream,业务层直接订阅即可。 - 错误旁路:若原生侧以
onError上报(Dart 侧表现为PlatformException),则进入errorStream统一处理,不会混入正常业务流。
使用示例
示例一:订阅设备连接状态
// 订阅设备连接事件(连接中 / 已连接 / 断开)
BleEventStream.deviceConnectionStream.listen((DeviceConnection connection) {
// 根据 connection.state 更新 UI 或业务状态
debugPrint('device connection: ${connection.state}');
});
Source: ble_event_stream.dart
示例二:订阅扫描结果与扫描状态
// 扫描状态(开始/停止)
BleEventStream.scanStateStream.listen((String state) {
// 处理扫描状态变化
});
// 扫描到的设备列表
BleEventStream.scanDeviceListStream.listen((List<ScanDevice> devices) {
// 刷新设备列表 UI
});
Source: ble_event_stream.dart
示例三:接收自定义命令原始数据
// 接收设备主动上报的自定义命令(原始字节)
BleEventStream.customCommandData.listen((Uint8List data) {
// 解析自定义协议字节
});
Source: ble_event_stream.dart
示例四:订阅底层广播流并自行过滤
// 高级用法:直接订阅未过滤的底层事件(仅当内置 Stream 不满足需求时)
BleEventStream.baseStream.listen((event) {
// event 为 Map,含 keyType/keyValue/keyData
});
Source: ble_event_stream.dart
示例五:统一错误处理
// 订阅错误流,统一展示原生侧错误信息
BleBaseEventProcessor.errorStream.listen((Map<String, String> error) {
final code = error[BleEventConstants.keyCode];
final message = error[BleEventConstants.keyMessage];
// 提示用户或记录日志
});
Source: ble_base_event_processor.dart
订阅时机建议:由于底层是广播流,页面在 initState 中订阅、在 dispose 中取消订阅是安全且推荐的做法;listen 返回的 StreamSubscription 应在页面销毁时 cancel(),避免在页面销毁后仍收到事件导致状态更新异常。
API 参考
BleEventStream(接收门面)
全部成员为静态属性,返回类型化的 Stream。按功能域分组:
核心与扫描连接
| 属性 | 类型 | 说明 |
|---|---|---|
baseStream | Stream<dynamic> | 底层原始广播流,未过滤,包含全部原生事件与 PlatformException |
scanStateStream | Stream<String> | 扫描状态变化 |
scanDeviceListStream | Stream<List<ScanDevice>> | 扫描到的设备列表 |
deviceConnectionStream | Stream<DeviceConnection> | 设备连接状态(连接中/已连接/断开) |
OTA
| 属性 | 类型 | 说明 |
|---|---|---|
otaConnectionStream | Stream<Map<String, dynamic>> | OTA 连接相关事件 |
otaFileListStream | Stream<List<Map<String, String>>> | OTA 固件文件列表 |
mandatoryUpgradeStream | Stream<bool> | 是否强制升级 |
otaStateStream | Stream<Map<String, dynamic>> | OTA 升级进度/状态 |
音频与设备音乐
| 属性 | 类型 | 说明 |
|---|---|---|
lineInStatusStream | Stream<int> | Line-in 状态 |
id3MusicInfoStream | Stream<MusicInfo> | ID3 歌曲信息 |
id3MusicStatusStream | Stream<int> | 音乐播放状态 |
fmInfoStream / musicInfoStream / musicProgressStream | Stream<Map<String, dynamic>> | FM / 音乐信息 / 播放进度 |
storageStatusStream | Stream<int> | 存储状态 |
deviceMusicTabTitleStream / deviceMusicItemModelArrayStream | Stream<List<DeviceMusicModel>> | 设备音乐页签与列表 |
deviceMusicPlayItemOKStream | Stream<void> | 设备音乐播放成功 |
deviceMusicLoadFailedStream | Stream<DMError> | 设备音乐加载失败(含错误) |
deviceMusicCardMessageDismissStream | Stream<List<dynamic>> | 音乐卡片消息消失 |
sdCardStatusStream | Stream<List<int>> | SD 卡状态 |
音量、灯光、EQ、声卡
| 属性 | 类型 | 说明 |
|---|---|---|
volumeInfoStream | Stream<VolumeInfo> | 音量信息 |
volumeCtrlStream | Stream<VolumeCtrlInfo> | 高低音控制信息 |
lightInfoStream | Stream<Map<String, dynamic>> | 灯光信息 |
reverberationAllDataStream | Stream<Map<String, dynamic>> | 混响/EQ 全量数据 |
soundCardSliderValuesStream | Stream<List<SoundCardSliderModel>> | 声卡滑杆值 |
soundCardSelectedStatusStream | Stream<List<dynamic>> | 声卡选中状态 |
SPDIF / PC 从机 / 双设备
| 属性 | 类型 | 说明 |
|---|---|---|
spDifPlayStatus | Stream<SPDIFPlayStatusInfo> | SPDIF 播放状态 |
spDifAudioType | Stream<SPDIFAudioSourceInfo> | SPDIF 音频源类型 |
pcSlavePlayStatus | Stream<PCSlavePlayStatusInfo> | PC 从机播放状态 |
doubleDeviceList | Stream<List<DoubleDeviceModel>> | 双设备列表 |
充电盒与 Auracast
| 属性 | 类型 | 说明 |
|---|---|---|
messagePushStateStream | Stream<MessagePushStateModel> | 消息推送状态 |
brightnessStream | Stream<double> | 亮度值 |
resourceListStream | Stream<ResourceListEvent> | 资源列表事件 |
uploadStateStream | Stream<UploadStateModel> | 上传状态 |
auraScanStateStream | Stream<bool> | Auracast 扫描状态 |
auraBroadcastListStream | Stream<List<AuraCastBroadcastModel>> | Auracast 广播列表 |
auraSyncStateStream | Stream<int> | Auracast 同步状态 |
auraConnectFailedStream | Stream<(String broadcastName, int errorCode)> | Auracast 连接失败(广播名+错误码,Dart record) |
auraBroadcastRecordListStream | Stream<List<AuraCastRecordStateModel>> | Auracast 广播记录列表 |
自定义命令与传输/翻译
| 属性 | 类型 | 说明 |
|---|---|---|
customCommandData | Stream<Uint8List> | 自定义命令原始字节数据 |
translationModeSuccessStream | Stream<bool> | 翻译模式切换成功 |
workTimeStream | Stream<String> | 翻译模式工作时长 |
translationModeChangedStream | Stream<int> | 翻译模式变更 |
deviceRecordStateStream | Stream<bool> | 设备录音状态 |
translationRecordStream | Stream<List<TranslationRecord>> | 翻译记录列表 |
simultaneousTranslateResultStream | Stream<Map<String, String>> | 同声传译结果 |
pcmDataStream | Stream<Int16List> | PCM 音频数据 |
saveSessionRecordSuccessStream | Stream<int> | 保存会话记录成功 |
sessionRecordChangedStream | Stream<TranslationSessionRecord> | 会话记录变化 |
playerStateChangedStream | Stream<int> | 播放器状态变化 |
stateResultChangedStream | Stream<StateResult<int>> | 状态结果变化 |
recordStateChangedStream | Stream<OpResult<TranslationRecord>> | 记录状态变化 |
BleBaseEventProcessor(基础工具)
| 成员 | 签名 | 说明 |
|---|---|---|
baseStream | static Stream<dynamic> get | 底层广播流(懒加载单例) |
errorStream | static Stream<Map<String, String>> get | 归一化的错误流(code/message) |
safeCastMap | static Map<String, dynamic> safeCastMap(dynamic data) | 安全转换为强类型 Map |
filterByType | static Stream<Map<String, dynamic>> filterByType(String type) | 按事件类型过滤广播流 |
getValueFromEvent | static Map<String, dynamic> getValueFromEvent(Map<String, dynamic> event) | 取事件 value 负载 |
getDataFromEvent | static dynamic getDataFromEvent(Map<String, dynamic> event) | 取事件 data 负载 |
Throws(errorStream 语义):当 PlatformException.code != BleEventConstants.error 时,errorStream 会重新抛出该异常,订阅者需自行捕获。
配置项
接收侧本身不暴露运行时配置;唯一"配置"是通道名常量:
| 项 | 值 | 说明 |
|---|---|---|
| EventChannel 名称 | com.jieli.home_plugin/events | 原生与 Dart 约定的唯一事件通道,两侧必须一致 |
| 事件键常量 | BleEventConstants.keyType / keyValue / keyData | 事件 Map 的键名,由常量类统一定义 |
事件类型的取值集合由 BleEventConstants 定义(与 ble_method_constants.dart 中的方法常量对应,构成完整的收发协议)。若需自定义事件,应扩展常量类并在原生侧同步实现,保持两侧通道与键名一致。
失败模式、边界情况与并发
失败模式
- 原生侧 onError 上报:表现为
PlatformException出现在广播流中。errorStream会拦截 code 为BleEventConstants.error的错误并归一化;其他 code 则原样抛出。订阅者若只订阅业务流而忽略errorStream,将无法感知原生错误。 - 事件负载类型不匹配:
safeCastMap对非 Map 数据返回空 Map,后续字段解析可能得到默认值;getValueFromEvent对缺失value返回空 Map,不会抛异常——这是"宽容解析"策略,代价是错误数据可能被静默吞掉,调试时需结合原生日志。 - 事件在订阅前发生:广播流不缓存历史事件,页面
initState之后才订阅会错过订阅前的事件。需要当前状态时,应配合发送接口主动查询一次状态(如通过方法通道读取设备当前音量),再依赖事件流做增量更新。
边界情况
- 事件类型字符串不匹配(大小写、拼写)时
filterByType过滤结果为空流,订阅方表现为"收不到事件",需核对BleEventConstants定义。 customCommandData/pcmDataStream是高频原始数据流(Uint8List/Int16List),若业务层消费过慢可能造成事件积压,建议在不需要时及时取消订阅。
并发与生命周期
- 底层广播流是单例,多订阅者并发订阅是安全的;
??=懒加载保证了通道只建立一次。 - 同一事件会被多个
filterByType流同时处理——设计上各 Processor 按type隔离,互不消费对方事件;但若两个 Processor 订阅了相同 type,则二者都会收到该事件(广播语义)。 - 页面销毁后未取消订阅会导致回调访问已销毁的 State,是典型的生命周期错误;应始终保存
StreamSubscription并在dispose中cancel()。
性能与运维注意事项
- 单通道聚合:所有事件共享一个 EventChannel,原生侧只需维护一个监听器;这是典型的"少通道、多类型"设计,通道建立成本被摊薄到全局,但也意味着事件量大时(如 PCM 数据流)所有订阅者都会收到广播流上的每一次推送,
where过滤有轻微开销。 - 高频流隔离:
pcmDataStream、customCommandData这类原始数据流建议仅在有界面需求时订阅,并在页面隐藏时取消,避免无谓的对象分配与 UI 刷新。 - 懒加载时机:
baseStream在首次访问时才建立通道。若应用启动后长期未订阅任何事件,原生侧事件将无人消费;建议在需要接收事件的模块初始化时尽早触发订阅。 - 调试建议:排查"收不到事件"问题时,先确认原生侧是否已推送(查看原生日志),再确认
BleEventConstants中的 type 字符串与原生侧一致;排查"事件重复"时,检查是否多处订阅了同一 Processor 的流(广播流会向每个订阅者各推送一份)。
扩展点
接收侧为新增事件类型提供了清晰的分层扩展路径:
- 新增事件类型:在
BleEventConstants中新增 type 常量(需与原生侧约定一致)。 - 新增/扩展 Processor:参考现有 Processor 模式——在
lib/processor/下创建BleXxxProcessor,内部用BleBaseEventProcessor.filterByType(新type)订阅广播流,解析value为模型,通过StreamController对外暴露类型化 Stream。 - 门面暴露:在
BleEventStream中增加对应的静态 getter,返回新 Processor 的 Stream,业务层即可统一通过门面订阅。 - 自定义命令通道:若设备协议是私有的,可直接订阅
customCommandData(Stream<Uint8List>)自行解析,无需改动插件接收层。
该分层(通道 → Processor → 门面)使得新增事件对业务层是纯增量:旧的 getter 不受影响,新事件通过新 getter 暴露,符合开闭原则。
测试
仓库在 code/JieLi_Home_Demo/example/integration_test/plugin_integration_test.dart 提供插件集成测试入口,用于验证插件在真实平台上的收发链路;示例应用(code/JieLi_Home_Demo/example/lib/data/ 下的各 Manager,如 translate_page_manager.dart、setting_manager.dart)展示了在真实页面中订阅 BleEventStream 事件流的典型用法,可作为订阅时序与生命周期管理的参考实现。
Source: plugin_integration_test.dart
相关链接
- ble_event_stream.dart — 接收门面,全部 Stream getter 定义处
- ble_base_event_processor.dart — 事件通道与基础解析工具
- ble_event_constants.dart — 事件类型与键名常量定义
- ble_method_constants.dart — 发送接口方法常量(对应"发送接口与方法参考"页面)
- ble_base_manager.dart — 插件基础管理器
- plugin_integration_test.dart — 集成测试
- 功能详情页:OTA 升级、翻译/传输、EQ 调音、Auracast 广播等功能的业务逻辑与发送接口,请参见各自功能页面。