import 'dart:async'; import 'dart:typed_data'; import 'package:flutter/services.dart'; /// BLE连接状态常量 class BleConnectionState { static const int disconnected = 0; static const int connecting = 1; static const int connected = 2; static const int disconnecting = 3; static const int error = 4; } /// BLE服务插件 class BleService { static final BleService _instance = BleService._internal(); /// 获取单例 factory BleService() => _instance; // 方法通道 final MethodChannel _methodChannel = const MethodChannel('com.yunqiinnovation.ble_service'); // 事件通道 - 简化为只使用数据和状态通道 late final EventChannel _dataEventChannel; late final EventChannel _statusEventChannel; // 事件流 late final Stream _dataStream; late final Stream _statusStream; // 获取事件流 Stream get onDataReceived => _dataStream; // 状态流直接传递原始数据 Stream get onStatusUpdated => _statusStream; // 内部构造函数 BleService._internal() { _dataEventChannel = const EventChannel('com.yunqiinnovation.ble_service/data_events'); _statusEventChannel = const EventChannel('com.yunqiinnovation.ble_service/status_events'); // 初始化事件流 _dataStream = _dataEventChannel.receiveBroadcastStream(); _statusStream = _statusEventChannel.receiveBroadcastStream(); } /// 检查是否已连接 Future isConnected() async { try { final result = await _methodChannel.invokeMethod('isConnected'); return result ?? false; } catch (e) { print('检查连接状态失败: $e'); return false; } } /// 获取电池电量 Future getBatteryLevel() async { try { final result = await _methodChannel.invokeMethod('getBatteryLevel'); return result ?? 0; } catch (e) { print('获取电池电量失败: $e'); return 0; } } /// 获取设备版本信息 Future getDeviceVersion() async { try { final result = await _methodChannel.invokeMethod('getDeviceVersion'); return result ?? false; } catch (e) { print('获取设备版本失败: $e'); return false; } } /// 获取产品ID Future getProductId() async { try { final result = await _methodChannel.invokeMethod('getProductId'); return result ?? false; } catch (e) { print('获取设备版本失败: $e'); return false; } } /// 获取电池信息 Future getBatteryInfo() async { try { final result = await _methodChannel.invokeMethod('getBatteryInfo'); return result ?? false; } catch (e) { print('获取电池信息失败: $e'); return false; } } /// 打开编码器 Future openEncoder() async { try { final result = await _methodChannel.invokeMethod('openEncoder'); return result ?? false; } catch (e) { print('打开编码器失败: $e'); return false; } } /// 打开解码器 Future openDecoder() async { try { final result = await _methodChannel.invokeMethod('openDecoder'); return result ?? false; } catch (e) { print('打开解码器失败: $e'); return false; } } /// 打开解码器 Future openA2DPDecoder() async { try { final result = await _methodChannel.invokeMethod('openA2DPDecoder'); return result ?? false; } catch (e) { print('打开解码器失败: $e'); return false; } } /// 打开解码器 Future openCallRecordDecoder() async { try { final result = await _methodChannel.invokeMethod('openCallRecordDecoder'); return result ?? false; } catch (e) { print('打开解码器失败: $e'); return false; } } /// 关闭编解码器 Future closeCodec() async { try { final result = await _methodChannel.invokeMethod('closeCodec'); return result ?? false; } catch (e) { print('关闭编解码器失败: $e'); return false; } } /// 播放A2DP Future playA2DP() async { try { final result = await _methodChannel.invokeMethod('playA2DP'); return result ?? false; } catch (e) { print('播放A2DP失败: $e'); return false; } } /// 设置通话翻译调试参数(运行时生效) /// [sendIntervalMs] 音频下行发送间隔(ms) /// [bundleFrameCount] 下行合包帧数 Future setCallTranslationDebugParams({ int? sendIntervalMs, int? bundleFrameCount, }) async { try { final result = await _methodChannel .invokeMethod('setCallTranslationDebugParams', { if (sendIntervalMs != null) 'sendIntervalMs': sendIntervalMs, if (bundleFrameCount != null) 'bundleFrameCount': bundleFrameCount, }); return result ?? false; } catch (e) { print('设置通话翻译调试参数失败: $e'); return false; } } /// 获取当前通话翻译调试参数 /// 返回 {'sendIntervalMs','bundleFrameCount'},失败返回空 Map Future> getCallTranslationDebugParams() async { try { final result = await _methodChannel .invokeMethod('getCallTranslationDebugParams'); if (result == null) return {}; int readInt(String k) => (result[k] as num?)?.toInt() ?? 0; return { 'sendIntervalMs': readInt('sendIntervalMs'), 'bundleFrameCount': readInt('bundleFrameCount'), }; } catch (e) { print('获取通话翻译调试参数失败: $e'); return {}; } } /// 启动BLE后台服务 Future startBleService(Map config) async { try { final result = await _methodChannel.invokeMethod('startBleService', config); return result ?? false; } catch (e) { print('启动BLE后台服务失败: $e'); return false; } } /// 停止BLE后台服务 Future stopBleService() async { try { final result = await _methodChannel.invokeMethod('stopBleService'); return result ?? false; } catch (e) { print('停止BLE后台服务失败: $e'); return false; } } //======================================================================== // 以下是Companion Device相关功能 //======================================================================== /// 检查设备是否支持Companion Device Manager /// /// 返回设备是否支持Companion Device Manager API /// 仅在Android 8.0及以上版本可用 Future isCompanionSupported() async { try { final result = await _methodChannel.invokeMethod('isCompanionSupported'); return result ?? false; } catch (e) { print('检查Companion设备支持失败: $e'); return false; } } /// 启动设备关联流程 /// /// 弹出系统设备选择对话框,用户选择后将建立持久化关联 /// 关联成功后,应用将获得后台扫描和启动前台服务的特权 /// /// [deviceNamePattern] 设备名称正则表达式,例如"MyHeadset.*" /// [serviceUuid] 可选的服务UUID /// [macAddress] 可选的MAC地址 /// /// 返回是否成功启动关联流程 Future startDeviceAssociation({ String? deviceNamePattern, String? serviceUuid, String? macAddress, }) async { try { final result = await _methodChannel.invokeMethod( 'startDeviceAssociation', { 'deviceNamePattern': deviceNamePattern, 'serviceUuid': serviceUuid, 'macAddress': macAddress, }, ); return result ?? false; } catch (e) { print('启动设备关联失败: $e'); return false; } } /// 获取已关联的设备MAC地址 /// /// 返回已关联的设备MAC地址,如果没有则返回null Future getPairedMacAddress() async { try { final result = await _methodChannel.invokeMethod('getPairedMacAddress'); return result; } catch (e) { print('获取配对MAC地址失败: $e'); return null; } } /// 检查BLE连接状态 /// /// 返回BLE是否已连接 Future isBleConnected() async { try { final result = await _methodChannel.invokeMethod('isBleConnected'); return result ?? false; } catch (e) { print('检查BLE连接状态失败: $e'); return false; } } /// 设置是否是ota模式 Future setEnterOta(bool enterOta) async { try { await _methodChannel.invokeMethod('setEnterOta', { 'enterOta': enterOta, }); } catch (e) { print('设置是否是ota模式失败: $e'); } } /// 设置是否是否需要唤醒 Future setWakeup(bool wakeup) async { try { await _methodChannel.invokeMethod('setWakeup', { 'wakeup': wakeup, }); } catch (e) { print('设置是否是否需要唤醒失败: $e'); } } /// 停止TTS播放 Future connect() async { try { await _methodChannel.invokeMethod('connect'); } catch (e) { print('连接设备失败: $e'); return; } } /// 断开连接 Future disconnect() async { try { await _methodChannel.invokeMethod('disconnect'); } catch (e) { print('断开连接失败: $e'); } } /// 断开连接 Future startScan(List uuids) async { try { final result = await _methodChannel .invokeMethod('startScan', {'uuids': uuids}); return result ?? false; } catch (e) { print('开启扫描ble设备失败: $e'); return false; } } /// 断开连接 Future stopScan() async { try { final result = await _methodChannel.invokeMethod('stopScan'); return result ?? false; } catch (e) { print('开启扫描ble设备失败: $e'); return false; } } /// 获取设备信息 Future?> getDeviceInfo(String deviceName) async { try { final result = await _methodChannel .invokeMethod('getDeviceInfo', {'deviceName': deviceName}); print('获取设备信息!: $result'); if (result != null) { return { 'name': result['name'] ?? "未知", 'address': result['address'] ?? "", 'id': result['id'] ?? result['address'] ?? "", // iOS 返回 UUID,Android 返回 address 'hex': result['hex'] ?? "", }; } else { return null; } } catch (e) { print('获取设备信息失败!: $e'); return null; } } /// 获取设备列表(通过设备名) Future>?> getDeviceList(String deviceName) async { try { final result = await _methodChannel .invokeMethod('getDeviceList', {'deviceName': deviceName}); print('获取设备列表!: $result'); if (result != null) { return result.map>((device) { return { 'name': device['name'] ?? "未知", 'address': device['address'] ?? "", 'id': device['id'] ?? device['address'] ?? "", // iOS 返回 UUID,Android 返回 address 'hex': device['hex'] ?? "", }; }).toList(); } else { return null; } } catch (e) { print('获取设备列表失败!: $e'); return null; } } /// 注册BLE后台扫描 /// /// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用 /// 这是确保设备可以在应用后台时被自动连接的关键功能 /// /// [macAddress] 可选的设备MAC地址,如果不提供则使用已关联的设备 Future registerBackgroundScan({ String? macAddress, List? uuids, }) async { try { final result = await _methodChannel.invokeMethod( 'registerBackgroundScan', { 'macAddress': macAddress, 'uuids': uuids, }, ); return result ?? false; } catch (e) { print('注册后台扫描失败: $e'); return false; } } /// 注销BLE后台扫描 /// /// 当不再需要后台扫描功能时调用,例如用户主动断开连接时 Future unregisterBackgroundScan() async { try { final result = await _methodChannel.invokeMethod('unregisterBackgroundScan'); return result ?? false; } catch (e) { print('注销后台扫描失败: $e'); return false; } } /// 清除所有设备关联 /// /// 用于重置设备关联状态,通常在用户主动解除关联或调试时使用 Future clearAssociations() async { try { final result = await _methodChannel.invokeMethod('clearAssociations'); return result ?? false; } catch (e) { print('清除设备关联失败: $e'); return false; } } //======================================================================== // 以下是ChatAgent相关功能 //======================================================================== /// 初始化语音交互代理 /// /// [config] 配置参数,必须包含: /// - azureSpeechKey: Azure语音服务API密钥 /// - azureSpeechRegion: Azure语音服务区域 /// - openaiApiKey: OpenAI API密钥 /// - openaiBaseUrl: OpenAI API基础URL /// - openaiModel: OpenAI模型名称,默认为'gpt-3.5-turbo' Future initializeChatAgent(Map config) async { try { final result = await _methodChannel.invokeMethod( 'initializeChatAgent', config); return result ?? false; } catch (e) { print('初始化语音交互代理失败: $e'); return false; } } /// 启动语音识别 /// /// 用于手动启动语音识别,通常不需要直接调用,因为在唤醒时会自动启动 Future startListening() async { try { final result = await _methodChannel.invokeMethod('startListening'); return result ?? false; } catch (e) { print('启动语音识别失败: $e'); return false; } } /// 停止语音识别 Future stopListening() async { try { final result = await _methodChannel.invokeMethod('stopListening'); return result ?? false; } catch (e) { print('停止语音识别失败: $e'); return false; } } /// 处理文本输入 /// /// [text] 用户输入的文本 /// [speakResponse] 是否使用TTS朗读回复,默认为false Future processTextInput(String text, {bool speakResponse = false}) async { try { final result = await _methodChannel.invokeMethod('processTextInput', { 'text': text, 'speakResponse': speakResponse, }); return result ?? false; } catch (e) { print('处理文本输入失败: $e'); return false; } } /// 停止TTS播放 Future stopTts() async { try { final result = await _methodChannel.invokeMethod('stopTts'); return result ?? false; } catch (e) { print('停止TTS播放失败: $e'); return false; } } /// 请求蓝牙权限(仅iOS) Future requestBluetoothPermission() async { try { final result = await _methodChannel.invokeMethod('requestBluetoothPermission'); return result ?? false; } catch (e) { print('请求蓝牙权限失败: $e'); return false; } } /// 开始唤醒词升级 /// 在收到唤醒信号时启动语音识别 Future startWakeupVoicesUpgrade(List wakeupVoiceBytes) async { try { final result = await _methodChannel.invokeMethod( 'startWakeupVoiceUpgrade', {"bytes": wakeupVoiceBytes}, ); return result ?? false; } catch (e) { print('开始唤醒词升级失败: $e'); return false; } } /// 查询语音唤醒状态 Future getVoiceWakeupStatus() async { try { final result = await _methodChannel.invokeMethod('getVoiceWakeupStatus'); return result ?? false; } catch (e) { print('查询语音唤醒状态失败: $e'); return false; } } /// 设置语音唤醒状态 Future setVoiceWakeupStatus(bool enabled) async { try { final result = await _methodChannel.invokeMethod( 'setVoiceWakeupStatus', {'enabled': enabled}, ); return result ?? false; } catch (e) { print('设置语音唤醒状态失败: $e'); return false; } } }