Auracast 音频广播
Auracast(LE Audio 音频广播)是蓝牙 5.2+ 规范中的广播音频功能,本页面介绍 JL SDK(jl_home)中 Auracast 从 Flutter 侧到原生 BLE 层的完整实现:发送接口 BleAuraCastManager、接收事件流 BleEventStream、示例应用 AuraCastReceiverManager 以及 Android/iOS 原生管理器。
Purpose and Scope
本页面覆盖 Auracast 音频广播能力在 JieLi_Home_Demo 仓库中的完整链路:
- Flutter SDK 层:
BleAuraCastManager(命令发送)与BleEventStream(状态/数据接收)的公开 API; - 示例应用层:
AuraCastReceiverManager(ChangeNotifier状态管理)、aura_cast_receiver_page.dart页面与aura_cast_animated_icon.dart动画组件; - 原生桥接层:Android 侧
AuraCastManager/AuraCastEventSender/AuraCastObserverManager,以及 iOSJL_BLEKit.framework中的JLAuracastManager系列头文件; - 数据模型与枚举:广播列表、记录状态、连接失败原因等。
以下内容不在此页面展开,由兄弟页面承载:蓝牙基础连接/配对(见"设备连接"相关页面)、EQ 音效(见"音频效果"目录下的其他页面)、TWS 等音频分发能力。
Overview
Auracast 允许音频源设备(如手机、电视)通过 LE Audio 广播音频流,任意"接收者"(耳机/音箱)可在附近扫描并收听广播,无需配对。本仓库将其落地为一条完整的 SDK 能力链:
- 扫描与发现:原生层启动 BLE 广播扫描,将附近 Auracast 广播列表上报到 Flutter;
- 订阅与同步:用户点击某个广播(可带密码),原生层建立广播同步(BIS 同步),期间持续上报同步状态;
- 记录管理:已同步过的广播会进入"我的设备"记录列表,支持再次点击加入、离开、移除;
- 失败反馈:密码错误、超时等失败原因通过事件流回传,UI 层据此弹出对应提示。
SDK 层通过 BleBaseManager.invokeMethod 走 MethodChannel 与原生通信;Flutter 侧职责被拆分为"发送命令"(BleAuraCastManager)与"接收事件"(BleEventStream)两个通道,这正是本仓库 SDK 的统一设计模式——命令与方法一一对应,事件以 Stream 形式订阅。
Architecture
flowchart TD
subgraph sg_UI["示例应用层 (example)"]
Page["aura_cast_receiver_page.dart"]
Manager["AuraCastReceiverManager<br/>(ChangeNotifier)"]
Icon["aura_cast_animated_icon.dart"]
Toast["ToastUtils / LoadingDialogWidget"]
end
subgraph sg_SDK["jl_home SDK (Flutter)"]
SendMgr["BleAuraCastManager<br/>(发送接口)"]
EventStream["BleEventStream<br/>(接收接口)"]
Proc["BleAuraCastProcessor"]
BaseMgr["BleBaseManager.invokeMethod"]
Models["AuraCastBroadcastModel /<br/>AuraCastRecordStateModel"]
end
subgraph sg_Native["原生桥接层"]
Android["Android: AuraCastManager /<br/>AuraCastEventSender /<br/>AuraCastObserverManager"]
iOS["iOS: JLAuracastManager /<br/>JLAuracastLancerManager"]
end
subgraph sg_BLE["BLE 协议层"]
LE["LE Audio 广播/同步<br/>(BIS/PA)"]
end
Page --> Manager
Manager --> SendMgr
Manager --> EventStream
Manager --> Toast
Page --> Icon
SendMgr --> BaseMgr
EventStream --> Proc
BaseMgr -->|"MethodChannel"| Android
BaseMgr -->|"MethodChannel"| iOS
Android --> LE
iOS --> LE
Proc --> Models
架构说明:
- UI 层(
AuraCastReceiverManager)是示例应用唯一与 SDK 交互的入口:它向BleAuraCastManager发命令,向BleEventStream订阅 5 条事件流,并把结果归一化为myDevices/nearbyDevices两个列表供页面渲染。 - SDK 层遵循"命令/事件分离":
BleAuraCastManager的方法名与BleMethodConstants中的方法常量一一对应(如methodAuraCastBroadClickIndex);BleEventStream则把BleAuraCastProcessor的底层流原样暴露给上层。 - 原生层负责真正的 BLE 操作:Android 的
AuraCastManager承载扫描/同步逻辑,AuraCastEventSender把事件回传 Flutter,AuraCastObserverManager管理观察者注册;iOS 侧由JL_BLEKit.framework的JLAuracastManager等类实现同等能力。
SDK 层实现详解
发送接口:BleAuraCastManager
BleAuraCastManager 位于 libs/Send Interface/ble_aura_cast_manager.dart,是 Auracast 的全部命令入口。所有方法都是 static,内部统一委托给 BleBaseManager.invokeMethod,以方法名常量 + 参数 Map 的形式调用原生层:
import '../ble_base_manager.dart';
import '../constant/ble_method_constants.dart';
/// AuraCast Manager
class BleAuraCastManager {
static Future<void> auraCastGetRecordList() async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastGetRecordList,
);
}
static Future<bool> sendAuraCastSwitchState(bool state) async {
return await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastSwitchState,
arguments: {BleMethodConstants.argAuraCastSwitchState: state},
);
}
static Future<void> clickAuraCastRecordBroadcast(int index) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastBroadRecordClickIndex,
arguments: {
BleMethodConstants.argAuraCastBroadRecordClickIndex: index
},
);
}
static Future<void> clickAuraCastRecordLeaveBroadcast(int index) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastBroadRecordLeaveClickIndex,
arguments: {
BleMethodConstants.argAuraCastBroadRecordLeaveClickIndex: index
},
);
}
static Future<void> clickAuraCastRecordRemoveBroadcast(int index) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastBroadRecordRemoveClickIndex,
arguments: {
BleMethodConstants.argAuraCastBroadRecordRemoveClickIndex: index
},
);
}
static Future<void> clickAuraCastBroadcast(int index, String password) async {
await BleBaseManager.invokeMethod(
BleMethodConstants.methodAuraCastBroadClickIndex,
arguments: {
BleMethodConstants.argAuraCastBroadClickIndex: index,
BleMethodConstants.argAuraCastBroadPassword: password
},
);
}
}
Source: ble_aura_cast_manager.dart
设计意图:方法被拆成三组语义——查询(auraCastGetRecordList)、开关(sendAuraCastSwitchState,返回 bool 表示原生是否成功切换扫描状态)、点击操作(连接/离开/移除,均以记录列表中的 index 定位目标)。点击类方法不返回结果,成败完全依赖事件流回传,因此 UI 层必须同时订阅状态流,这是"命令-事件"异步模型的核心约定。
接收接口:BleEventStream 的 Auracast 事件流
BleEventStream(libs/Receive Interface/ble_event_stream.dart)把 BleAuraCastProcessor 的底层流统一封装为 5 条静态 Stream,覆盖 Auracast 全部上行事件:
// Get auraCast scan state
static Stream<bool> get auraScanStateStream =>
BleAuraCastProcessor.auraScanStateStream;
// Get auraCast broadcast list
static Stream<List<AuraCastBroadcastModel>> get auraBroadcastListStream =>
BleAuraCastProcessor.auraBroadcastListStream;
// Get auraCast broadcast state
static Stream<int> get auraSyncStateStream =>
BleAuraCastProcessor.auraSyncStateStream;
// Get auraCast broadcast connect fail
static Stream<(String broadcastName, int errorCode)> get auraConnectFailedStream =>
BleAuraCastProcessor.auraConnectFailedStream;
// Get auraCast broadcast record list
static Stream<List<AuraCastRecordStateModel>> get auraBroadcastRecordListStream =>
BleAuraCastProcessor.auraBroadcastRecordListStream;
Source: ble_event_stream.dart
各流语义如下:
| 事件流 | 类型 | 触发时机 |
|---|---|---|
auraScanStateStream | Stream<bool> | 原生扫描开关状态变化(true = 扫描中) |
auraBroadcastListStream | Stream<List<AuraCastBroadcastModel>> | 附近广播列表刷新 |
auraSyncStateStream | Stream<int> | 广播同步状态变化(对应 SyncState 枚举下标) |
auraConnectFailedStream | Stream<(String, int)> | 连接/同步失败,携带广播名与错误码 |
auraBroadcastRecordListStream | Stream<List<AuraCastRecordStateModel>> | "我的设备"记录列表更新 |
ble_event_stream.dart 顶部还引入了 model/auracast_broadcast_model.dart 与 model/auracast_reecord_state_model.dart 两个数据模型,说明 SDK 层为 Auracast 专门定义了广播模型与记录状态模型,事件流的泛型即由这两个模型承载。
设计意图:把 5 条流直接暴露而非封装成回调,使 UI 层可以按需订阅、用 StreamSubscription 精确管理生命周期;auraConnectFailedStream 使用 Dart 3 的 record 类型 (String, int) 打包"广播名 + 错误码",避免为单次失败事件新建 DTO。
数据模型与枚举
示例应用层定义了与 SDK 事件流对齐的枚举(见 aura_cast_receiver_manager.dart):
enum SyncState {
syncing,
idle,
syncOk,
}
enum ConnectFailReason {
badPassword,
timeout,
other;
static ConnectFailReason fromInt(int value) {
switch (value) {
case 0:
return ConnectFailReason.badPassword;
case 1:
return ConnectFailReason.timeout;
default:
return ConnectFailReason.other;
}
}
}
enum StateCode {
idle,
syncing,
syncOk,
}
enum AuraCastDeviceState {
normal,
leave,
}
Source: aura_cast_receiver_manager.dart
错误码映射规则(ConnectFailReason.fromInt):0 = 密码错误(badPassword),1 = 超时(timeout),其余一律归为 other。该映射由原生层错误码定义驱动,UI 层据此选择多语言提示文案。
示例应用实现详解:AuraCastReceiverManager
AuraCastReceiverManager 继承 ChangeNotifier,是示例应用 Auracast 页面的状态中枢(位于 code/JieLi_Home_Demo/example/lib/manager/aura_cast_receiver_manager.dart)。它把 SDK 的 5 条事件流与 6 个命令方法归一化为页面可直接绑定的两个列表:myDevices(我的设备/记录)与 nearbyDevices(附近广播)。
初始化与生命周期
void init(BuildContext ctx) {
context = ctx;
BleAuraCastManager.auraCastGetRecordList();
_listenAllStreams();
}
/// 统一订阅所有流
void _listenAllStreams() {
_listenToScanState();
_listenToBroadcastList();
_listenToBroadCastState();
_listenToConnectFailed();
_listenToBroadcastRecordList();
}
void disposeSubscriptions() {
_scanStateSubscription?.cancel();
_broadcastListSubscription?.cancel();
_auraCastStateSubscription?.cancel();
_connectFailedSubscription?.cancel();
_recordListSubscription?.cancel();
myDevices.clear();
nearbyDevices.clear();
}
Source: aura_cast_receiver_manager.dart
init 先主动拉取一次记录列表(auraCastGetRecordList),再统一订阅 5 条流;disposeSubscriptions 必须成对调用以取消订阅并清空列表,避免页面销毁后收到原生事件导致内存泄漏或对已卸载 BuildContext 操作崩溃。
事件归一化逻辑
每条流的监听都做了"SDK 模型 → UI 展示数据"的转换,是理解整个页面的关键:
void _listenToBroadcastList() {
_broadcastListSubscription = BleEventStream.auraBroadcastListStream.listen(
(broadcastList) {
nearbyDevices = broadcastList.map((model) {
return {
BleEventConstants.keyBroadCastName: model.broadcastName,
BleEventConstants.keyIsEncrypted: model.isEncrypted,
};
}).toList();
notifyListeners();
},
);
}
void _listenToBroadcastRecordList() {
_recordListSubscription =
BleEventStream.auraBroadcastRecordListStream.listen((recordList) {
bool hasSyncing = recordList.any(
(r) => r.syncState == StateCode.syncing.index);
if (hasSyncing) {
_showLoadingDialog();
} else {
_dismissLoadingDialog();
}
myDevices = recordList.map((record) {
bool isOk = record.syncState == StateCode.syncOk.index;
return {
BleEventConstants.keyBroadCastName:
record.broadcast?.broadcastName,
BleEventConstants.keyPlayAnimationState: isOk,
BleEventConstants.keyIsFoundBroadCast:
record.isFoundBroadcast,
BleEventConstants.keyAuraCastDeviceState:
isOk ? AuraCastDeviceState.normal : AuraCastDeviceState.leave,
};
}).toList();
notifyListeners();
});
}
Source: aura_cast_receiver_manager.dart
要点:
- 附近列表只保留
broadcastName(广播名)与isEncrypted(是否加密)——加密项在 UI 上需要弹出密码输入框; - 记录列表把
syncState == StateCode.syncOk映射为"播放动画状态"与AuraCastDeviceState.normal;未同步成功则标记为leave(已离开); - 只要记录中存在任一
syncing项,就弹全局 Loading 对话框(LoadingDialogWidget),全部同步完成才关闭——用"任一同步中"来驱动遮罩,避免多次弹窗竞态。
用户操作入口
Future<bool> sendSwitchState(bool value) async {
return await BleAuraCastManager.sendAuraCastSwitchState(value);
}
Future<void> clickRecordBroadcast(int index) async {
notifyListeners();
await BleAuraCastManager.clickAuraCastRecordBroadcast(index);
}
Future<void> clickNearbyBroadcast(int index, String password) async {
notifyListeners();
await BleAuraCastManager.clickAuraCastBroadcast(index, password);
}
Source: aura_cast_receiver_manager.dart
点击类操作在发送前先 notifyListeners() 立即刷新 UI(如切换 loading 状态),再异步等待原生执行——这是"乐观更新"策略,保证交互即时反馈。
连接失败提示
void _listenToConnectFailed() {
_connectFailedSubscription = BleEventStream.auraConnectFailedStream.listen(
(failInfo) {
// 缓存安全 context
final ctx = context;
if (!ctx.mounted) return;
final (name, code) = failInfo;
final loc = AppLocalizations.of(ctx)!;
final reason = ConnectFailReason.fromInt(code);
String message;
switch (reason) {
case ConnectFailReason.badPassword:
message = loc.badPasswordTips(name);
break;
case ConnectFailReason.timeout:
message = loc.syncTimeoutTips(name);
break;
case ConnectFailReason.other:
message = loc.syncFailedTips(name);
break;
}
ToastUtils.show(ctx, message);
},
);
}
Source: aura_cast_receiver_manager.dart
这里缓存了 BuildContext 并在使用前检查 ctx.mounted,再通过 AppLocalizations 按错误码选择多语言提示文案(badPasswordTips / syncTimeoutTips / syncFailedTips),最后用 ToastUtils.show 展示。这是异步回调中安全使用 Flutter Context 的标准姿势。
Core Flow
sequenceDiagram
participant U as 用户
participant P as AuraCastReceiverPage
participant M as AuraCastReceiverManager
participant S as BleAuraCastManager (SDK)
participant E as BleEventStream (SDK)
participant N as 原生 AuraCastManager
U->>P: 打开 Auracast 页面
P->>M: init(context)
M->>S: auraCastGetRecordList()
M->>E: 订阅 5 条事件流
U->>P: 打开广播开关
P->>M: sendSwitchState(true)
M->>S: sendAuraCastSwitchState(true)
S->>N: methodAuraCastSwitchState
N-->>E: auraScanStateStream(true)
N-->>E: auraBroadcastListStream(附近广播列表)
E-->>M: 更新 nearbyDevices / broadcastSwitch
M-->>P: notifyListeners() 渲染列表
U->>P: 点击某个加密广播并输入密码
P->>M: clickNearbyBroadcast(index, password)
M->>S: clickAuraCastBroadcast(index, password)
S->>N: methodAuraCastBroadClickIndex + password
N-->>E: auraSyncStateStream(syncing)
E-->>M: _showLoadingDialog()
alt 同步成功
N-->>E: auraBroadcastRecordListStream(记录 syncOk)
E-->>M: myDevices 更新, dismiss dialog
M-->>P: 列表项显示播放动画
else 同步失败
N-->>E: auraConnectFailedStream(name, code)
E-->>M: ConnectFailReason.fromInt(code)
M-->>P: ToastUtils 提示 密码错误/超时/失败
end
流程要点:所有 UI 状态变化都来自事件流而非命令返回值(sendAuraCastSwitchState 除外,它返回 bool)。同步期间由"记录列表中存在 syncing 项"驱动 Loading 遮罩;失败路径由 auraConnectFailedStream 携带的 (broadcastName, errorCode) 决定提示文案。这个"命令只管发、状态全靠流"的模型,保证原生层任意时刻的状态变化都能准确反映到 UI。
原生层桥接
MethodChannel 的另一端是各平台的原生实现。仓库中可确认的原生 Auracast 文件如下:
Android(Kotlin/Java,JL SDK)
code/JieLi_Home_Demo/android/src/main/kotlin/com/jieli/bt/sdk/data/manager/auracast/ 目录下:
AuraCastManager.kt:Auracast 核心管理器,承接 Flutter 侧 6 个方法(扫描开关、广播点击、记录管理),维护扫描状态与广播列表;AuraCastEventSender.kt:事件发送器,把扫描状态、广播列表、同步状态、连接失败、记录列表五类事件通过通道回调到 Flutter,是BleEventStream各条流的原生源头;AuraCastObserverManager.kt:观察者注册/注销管理,向 SDK 的扫描与同步回调注册监听,再转发给AuraCastEventSender。
data/model/auracast/ 下还有配套模型:AuraCastAssistantViewModel.java、AuraCastReceiverViewModel.kt(接收者视图模型)、AuraCastRecordOp.java(记录操作)、AuracastRecordState.java(记录状态,对应 Flutter 侧 AuraCastRecordStateModel)。
iOS(JL_BLEKit.framework)
code/JieLi_Home_Demo/example/ios/JL_BLEKit.framework/Headers/ 下的头文件:
JLAuracastManager.h:iOS 侧 Auracast 管理器,与 AndroidAuraCastManager对应;JLAuracastLancerManager.h与JLAuracastLancerSettingMode.h:广播发起者(Lancer)管理与设置模型,对应"作为音频源发起广播"的场景;JLAuracastDevStateModel.h:设备状态模型。
注:Android/iOS 原生文件仅经目录与文件清单确认,其内部实现细节未在本次文档生成过程中逐行阅读;如需精确的原生流程,请直接查阅上述文件。
配置与常量
示例应用通过 BleEventConstants 定义列表 Map 的键名,UI 层与数据归一化共用同一组常量:
| 常量键 | 含义 | 使用位置 |
|---|---|---|
keyBroadCastName | 广播名称 | nearbyDevices / myDevices 列表项 |
keyIsEncrypted | 是否加密广播 | 附近列表项,决定是否弹密码输入 |
keyPlayAnimationState | 是否播放同步成功动画 | myDevices 列表项,驱动 aura_cast_animated_icon.dart |
keyIsFoundBroadCast | 广播是否仍被发现 | myDevices 列表项 |
keyAuraCastDeviceState | 设备状态(normal/leave) | myDevices 列表项,绑定 AuraCastDeviceState |
SDK 侧的方法常量(BleMethodConstants)与参数常量(argAuraCast*)在 ble_aura_cast_manager.dart 中被引用,构成了与原生层的协议契约:
| 方法常量 | 参数常量 | 语义 |
|---|---|---|
methodAuraCastGetRecordList | — | 拉取广播记录列表 |
methodAuraCastSwitchState | argAuraCastSwitchState | 设置扫描开关 |
methodAuraCastBroadRecordClickIndex | argAuraCastBroadRecordClickIndex | 点击记录中的广播(重新加入) |
methodAuraCastBroadRecordLeaveClickIndex | argAuraCastBroadRecordLeaveClickIndex | 离开记录中的广播 |
methodAuraCastBroadRecordRemoveClickIndex | argAuraCastBroadRecordRemoveClickIndex | 移除记录 |
methodAuraCastBroadClickIndex | argAuraCastBroadClickIndex、argAuraCastBroadPassword | 点击附近广播并携带密码 |
API Reference
BleAuraCastManager(发送接口)
| 方法签名 | 参数 | 返回 | 说明 |
|---|---|---|---|
auraCastGetRecordList() | 无 | Future<void> | 请求原生返回"我的设备"记录列表,结果经 auraBroadcastRecordListStream 回传 |
sendAuraCastSwitchState(bool state) | state:目标开关状态 | Future<bool> | 设置广播扫描开关;返回值为原生执行结果 |
clickAuraCastRecordBroadcast(int index) | index:记录列表下标 | Future<void> | 重新加入历史记录中的广播 |
clickAuraCastRecordLeaveBroadcast(int index) | index:记录列表下标 | Future<void> | 离开某个已同步广播 |
clickAuraCastRecordRemoveBroadcast(int index) | index:记录列表下标 | Future<void> | 从记录中删除广播 |
clickAuraCastBroadcast(int index, String password) | index:附近列表下标;password:广播密码(无密码传空串) | Future<void> | 点击附近广播发起同步 |
BleEventStream(接收接口,Auracast 部分)
| 属性 | 类型 | 说明 |
|---|---|---|
auraScanStateStream | Stream<bool> | 扫描开关状态;true 表示扫描中 |
auraBroadcastListStream | Stream<List<AuraCastBroadcastModel>> | 附近广播列表,元素含 broadcastName、isEncrypted |
auraSyncStateStream | Stream<int> | 同步状态,取值对应 SyncState:syncing=0、idle=1、syncOk=2 |
auraConnectFailedStream | Stream<(String, int)> | 连接失败事件;record 第一项为广播名,第二项为错误码(0=密码错误,1=超时) |
auraBroadcastRecordListStream | Stream<List<AuraCastRecordStateModel>> | 记录列表,元素含 broadcast、syncState、isFoundBroadcast |
失败模式、边界情况与并发
连接/同步失败分类
auraConnectFailedStream 是唯一携带错误码的事件通道,原生错误码被收敛为三种原因(见 ConnectFailReason):
| 错误码 | 原因 | UI 提示(i18n key) | 应对 |
|---|---|---|---|
0 | 密码错误(badPassword) | badPasswordTips(name) | 提示用户重新输入密码,再次调用 clickAuraCastBroadcast |
1 | 同步超时(timeout) | syncTimeoutTips(name) | 提示超时,建议重试或检查信号 |
| 其他 | 未知失败(other) | syncFailedTips(name) | 通用失败提示 |
生命周期边界
- Context 失效:
_listenToConnectFailed在异步回调中缓存context并检查ctx.mounted,未挂载直接返回,防止对已销毁页面操作; - 订阅泄漏:页面销毁必须调用
disposeSubscriptions()取消全部 5 条StreamSubscription并清空列表,否则原生事件会继续驱动已不可见的ChangeNotifier; - Loading 竞态:
_showLoadingDialog通过LoadingDialogWidget.isShowing判重,并用addPostFrameCallback延后到下一帧再弹窗,避免快速连续事件导致重复弹窗; - 记录状态转换:记录项只有
syncState == syncOk才进入AuraCastDeviceState.normal,否则一律leave——"同步中"的记录会先显示 Loading 遮罩,待结果返回后一次性收敛为成功或失败,避免中间态闪烁。
并发与一致性
- 点击类命令(连接/离开/移除)都以
index定位列表项,UI 层在发送前notifyListeners()做乐观更新;若原生快速回推列表刷新事件,nearbyDevices/myDevices会整体重建,因此页面渲染必须容忍列表项按index的重排; - 多条流相互独立:扫描状态、广播列表、同步状态可能在同一时刻到达,管理器按流分别处理再统一
notifyListeners(),保证单帧内状态一致; - 同步中记录的检测使用
any()聚合("任一同步中即弹遮罩"),多广播并发同步时遮罩的关闭时机以最后一条记录状态更新为准。
性能与运维注意
- 事件流是高频通道:广播扫描期间
auraBroadcastListStream可能频繁推送,UI 层每次全量重建nearbyDevicesMap 列表。若广播数量大,建议在页面层做节流或差分渲染(当前示例应用未做该优化); - Loading 遮罩开销:
isShowing全局判重避免重复弹窗,但addPostFrameCallback的延迟弹窗在极端快速的成功/失败切换下可能产生一次多余闪烁; - 多语言文案:所有提示文案经
AppLocalizations按错误码映射,新增语言只需补充badPasswordTips/syncTimeoutTips/syncFailedTips对应翻译; - 原生层责任:扫描启动/停止、BIS 同步、记录持久化均在原生
AuraCastManager(Android)/JLAuracastManager(iOS)内完成,Flutter 侧只做透传与展示,性能敏感路径应优先在原生排查。
扩展点
- 自定义 Auracast 页面:可复制
aura_cast_receiver_page.dart与aura_cast_animated_icon.dart的组合,复用AuraCastReceiverManager的状态模型与全部 SDK API,仅替换 UI 布局; - 新增广播类型/操作:在
BleAuraCastManager增加静态方法 +BleMethodConstants新增方法常量,并在原生两侧(AuraCastManager.kt/JLAuracastManager.h实现)同步注册通道处理; - 失败提示定制:
ConnectFailReason.fromInt是 UI 层映射,可按业务需要扩展错误码分支或替换提示组件(当前使用ToastUtils); - 广播发起(Lancer)场景:iOS 侧已存在
JLAuracastLancerManager/JLAuracastLancerSettingMode,仓库为"作为音频源发起广播"预留了原生能力;Flutter SDK 层是否已封装对应方法需以BleMethodConstants与BleAuraCastManager最新代码为准。
测试情况说明
本次文档生成受源码读取预算限制,未定位到 Auracast 专属的 Flutter 单元测试/集成测试文件。仓库中该能力的正确性主要依赖:原生层 SDK 回调协议(AuraCastEventSender 五类事件)与示例应用 UI 的联调验证。建议在使用或扩展前,先以真机跑通"扫描 → 加入 → 同步成功/失败 → 记录管理"全链路。