diff --git a/lib/modules/home/controllers/home_controller.dart b/lib/modules/home/controllers/home_controller.dart index 04c687ba0..807546e01 100644 --- a/lib/modules/home/controllers/home_controller.dart +++ b/lib/modules/home/controllers/home_controller.dart @@ -22,6 +22,10 @@ class HomeController extends GetxController { // 连接状态相关 final _isFullyConnected = false.obs; + // 缓存最后连接的设备信息,用于断开后短暂显示 + String? _lastConnectedDeviceName; + String? _lastConnectedDeviceAddress; + // Getter方法 bool get isFullyConnected => _isFullyConnected.value; RxBool get isFullyConnectedRx => _isFullyConnected; // 响应式getter供UI使用 @@ -82,10 +86,8 @@ class HomeController extends GetxController { // 设置监听器 _setupStateListeners(); - // 延迟检查初始连接状态,确保监听器已经设置 - Future.delayed(const Duration(milliseconds: 100), () { - _checkConnectionStatus(); - }); + // 立即检查初始连接状态 + _checkConnectionStatus(); } /// 设置状态监听器 @@ -102,29 +104,26 @@ class HomeController extends GetxController { // 经典蓝牙连接监听 _classicBluetoothWorker = ever(_bluetoothManager.currentDeviceRx, (BluetoothDevice? device) { Logger.d(_tag, '经典蓝牙: ${device != null ? "已连接" : "已断开"}'); + // 保存设备信息用于断开后显示 + if (device != null) { + _lastConnectedDeviceName = device.name; + _lastConnectedDeviceAddress = device.address; + } + // 立即检查状态,不使用延迟 _checkConnectionStatus(); - // 额外的刷新确保UI更新 - Future.delayed(const Duration(milliseconds: 50), () { - _isFullyConnected.refresh(); - update(); - }); }); // BLE连接监听 _bleConnectionWorker = ever(_bleManager.connectionStateRx, (int state) { Logger.d(_tag, 'BLE状态变化: $state (${state == 2 ? "已连接" : "未连接"})'); + // 立即检查状态,不使用延迟 _checkConnectionStatus(); - // 额外的刷新确保UI更新 - Future.delayed(const Duration(milliseconds: 50), () { - _isFullyConnected.refresh(); - update(); - }); }); } /// 刷新设备连接状态 Future refreshDeviceConnection() async { - _checkConnectionStatus(); + await _checkConnectionStatus(); } // 导航和功能方法 @@ -147,47 +146,53 @@ class HomeController extends GetxController { // UI辅助方法 /// 检查连接状态 - void _checkConnectionStatus() { - // 直接检查,不使用延迟 - bool hasClassicBluetooth = currentDevice != null; - bool hasBleConnection = _bleManager.connectionState == 2; // 直接检查状态值,2 = connected - - Logger.d(_tag, '连接状态检查: 经典蓝牙=$hasClassicBluetooth, BLE=$hasBleConnection (状态值=${_bleManager.connectionState})'); - - bool wasConnected = _isFullyConnected.value; - bool isNowConnected = hasClassicBluetooth && hasBleConnection; - - // 只有状态真正改变时才更新 - if (_isFullyConnected.value != isNowConnected) { - // 先更新状态 - _isFullyConnected.value = isNowConnected; - Logger.d(_tag, '连接状态变更: ${wasConnected ? "已连接" : "未连接"} -> ${isNowConnected ? "已连接" : "未连接"}'); + Future _checkConnectionStatus() async { + try { + // 主动从原生层获取最新的BLE状态 + final currentBleState = await _bleManager.getConnectionState(); + + bool hasClassicBluetooth = currentDevice != null; + bool hasBleConnection = currentBleState == 2; // 使用实时查询的状态 - // 强制触发响应式更新 - _isFullyConnected.refresh(); + Logger.d(_tag, '连接状态检查: 经典蓝牙=$hasClassicBluetooth, BLE=$hasBleConnection (实时状态值=$currentBleState)'); - // 如果从未连接变为连接,主动获取耳机信息 - if (!wasConnected && isNowConnected) { - Logger.d(_tag, '设备连接成功,获取耳机信息'); - _bleManager.fetchDeviceInfo(); + bool wasConnected = _isFullyConnected.value; + bool isNowConnected = hasClassicBluetooth && hasBleConnection; + + // 状态一致性检查:如果声称已连接但没有设备信息,强制断开 + if (isNowConnected && currentDevice == null) { + Logger.w(_tag, '状态不一致:已连接但无设备信息,强制更新为未连接'); + isNowConnected = false; } - // 延迟一帧后再次刷新,确保UI更新 - Future.delayed(Duration.zero, () { - update(); - // 再次强制刷新响应式变量 + // 只有状态真正改变时才更新 + if (_isFullyConnected.value != isNowConnected) { + // 立即同步更新状态 + _isFullyConnected.value = isNowConnected; + Logger.d(_tag, '连接状态变更: ${wasConnected ? "已连接" : "未连接"} -> ${isNowConnected ? "已连接" : "未连接"}'); + + // 立即触发UI更新,不使用延迟 _isFullyConnected.refresh(); - }); - - // 延迟稍长时间再刷新一次,处理某些特殊情况 - Future.delayed(const Duration(milliseconds: 100), () { update(); + + // 如果从未连接变为连接,主动获取耳机信息 + if (!wasConnected && isNowConnected) { + Logger.d(_tag, '设备连接成功,获取耳机信息'); + await _bleManager.fetchDeviceInfo(); + } + } + + // 确保UI刷新 + update(); + } catch (e) { + Logger.e(_tag, '检查连接状态失败: $e'); + // 出错时设置为未连接 + if (_isFullyConnected.value) { + _isFullyConnected.value = false; _isFullyConnected.refresh(); - }); + update(); + } } - - // 总是调用update确保UI刷新 - update(); } /// 获取连接状态对应的颜色 @@ -209,7 +214,29 @@ class HomeController extends GetxController { /// 获取设备名称 String getDeviceName() { - return currentDevice?.name ?? 'unknownEquipment'.tr; + // 状态一致性检查 + if (_isFullyConnected.value && currentDevice == null) { + Logger.w(_tag, '状态不一致:显示已连接但无设备信息'); + // 立即重新检查状态 + _checkConnectionStatus(); + } + + // 优先使用当前设备名称 + if (currentDevice?.name != null && currentDevice!.name!.isNotEmpty) { + return currentDevice!.name!; + } + + // 如果当前没有设备但有BLE设备信息,使用BLE的设备名 + if (deviceInfo.value?.name != null && deviceInfo.value!.name.isNotEmpty) { + return deviceInfo.value!.name; + } + + // 如果刚断开连接,使用缓存的设备名称(提供更好的用户体验) + if (!_isFullyConnected.value && _lastConnectedDeviceName != null && _lastConnectedDeviceName!.isNotEmpty) { + return _lastConnectedDeviceName!; + } + + return 'unknownEquipment'.tr; } /// 获取信号强度(模拟数据) diff --git a/lib/modules/pairing/controllers/pairing_controller.dart b/lib/modules/pairing/controllers/pairing_controller.dart index 7ee1a66f2..34574e0f0 100644 --- a/lib/modules/pairing/controllers/pairing_controller.dart +++ b/lib/modules/pairing/controllers/pairing_controller.dart @@ -15,6 +15,7 @@ enum PairingState { checking, // 检查中(蓝牙、权限等) waitingClassic, // 等待经典蓝牙连接 verifying, // 验证设备 + associating, // 正在进行BLE设备关联 waitingBle, // 等待BLE连接 completed, // 配对完成 error, // 错误状态 @@ -28,6 +29,7 @@ enum ErrorType { noClassicDevice, // 无经典蓝牙设备 deviceNotMatch, // 设备不匹配 deviceBound, // 设备已被绑定 + associationFailed, // 关联失败 bleTimeout, // BLE连接超时 networkError, // 网络错误 } @@ -261,6 +263,15 @@ class PairingController extends GetxController { isLoading.value = true; break; + case PairingState.associating: + statusText.value = '正在关联设备...'; + isLoading.value = true; + // 延迟执行关联,确保状态已更新 + Future.delayed(const Duration(milliseconds: 200), () { + _startDeviceAssociation(); + }); + break; + case PairingState.waitingBle: statusText.value = '正在建立安全连接...'; isLoading.value = true; @@ -295,6 +306,10 @@ class PairingController extends GetxController { showRetryButton.value = true; retryButtonText.value = '授予权限'; break; + case ErrorType.associationFailed: + showRetryButton.value = true; + retryButtonText.value = '重新关联'; + break; default: showRetryButton.value = true; retryButtonText.value = '重试'; @@ -394,16 +409,27 @@ class PairingController extends GetxController { Logger.i(_tag, '设备验证通过'); _verifiedDeviceAddress = device.address; - // 检查BLE状态 - 直接从原生层获取 - final currentBleState = await _bleManager.getConnectionState(); - Logger.i(_tag, '验证时BLE状态: $currentBleState'); + // 检查是否已有BLE关联 + final pairedMacAddress = await _bleManager.getPairedMacAddress(); + Logger.i(_tag, '已关联的MAC地址: $pairedMacAddress'); - if (currentBleState == 2) { // BleConnectionState.connected - Logger.i(_tag, 'BLE已连接,直接完成配对'); - _transition(PairingState.completed); + if (pairedMacAddress != null && pairedMacAddress.toUpperCase() == device.address.toUpperCase()) { + // 已有关联,检查BLE连接状态 + Logger.i(_tag, '设备已关联,检查BLE连接状态'); + final currentBleState = await _bleManager.getConnectionState(); + Logger.i(_tag, '验证时BLE状态: $currentBleState'); + + if (currentBleState == 2) { // BleConnectionState.connected + Logger.i(_tag, 'BLE已连接,直接完成配对'); + _transition(PairingState.completed); + } else { + Logger.i(_tag, 'BLE未连接,等待BLE连接'); + _transition(PairingState.waitingBle); + } } else { - Logger.i(_tag, 'BLE未连接,等待BLE连接'); - _transition(PairingState.waitingBle); + // 没有关联或关联的是其他设备,需要进行关联 + Logger.i(_tag, '需要进行BLE设备关联'); + _transition(PairingState.associating); } } else { _setError(ErrorType.deviceNotMatch, '请连接 DeepSound 设备'); @@ -414,6 +440,35 @@ class PairingController extends GetxController { } } + /// 开始设备关联 + void _startDeviceAssociation() async { + try { + if (_verifiedDeviceAddress == null) { + _setError(ErrorType.associationFailed, '设备地址无效'); + return; + } + + Logger.i(_tag, '开始BLE设备关联: $_verifiedDeviceAddress'); + + // 调用BLE管理器的关联方法 + final success = await _bleManager.startDeviceAssociation( + deviceNamePattern: 'DeapSound', // 或者使用 _currentClassicDevice?.name + macAddress: _verifiedDeviceAddress!, + ); + + if (success) { + Logger.i(_tag, 'BLE设备关联成功'); + // 关联成功后,转到等待BLE连接状态 + _transition(PairingState.waitingBle); + } else { + _setError(ErrorType.associationFailed, 'BLE设备关联失败'); + } + } catch (e) { + Logger.e(_tag, 'BLE设备关联异常: $e'); + _setError(ErrorType.associationFailed, '设备关联失败,请重试'); + } + } + /// 开始BLE连接 void _startBleConnection() async { try { @@ -517,4 +572,14 @@ class PairingController extends GetxController { void openBluetoothSettings() { AppSettings.openAppSettings(type: AppSettingsType.bluetooth); } + + /// 清除设备关联(在需要重新配对时调用) + Future clearDeviceAssociation() async { + try { + Logger.i(_tag, '清除设备关联'); + await _bleManager.clearPairedDevices(); + } catch (e) { + Logger.e(_tag, '清除设备关联失败: $e'); + } + } } \ No newline at end of file diff --git a/lib/modules/pairing/views/pairing_view.dart b/lib/modules/pairing/views/pairing_view.dart index e0577cdf1..b0cf500c3 100644 --- a/lib/modules/pairing/views/pairing_view.dart +++ b/lib/modules/pairing/views/pairing_view.dart @@ -234,6 +234,8 @@ class PairingView extends GetView { switch (state) { case PairingState.completed: return Icons.check_circle; + case PairingState.associating: + return Icons.link; case PairingState.error: final errorType = controller.errorType; switch (errorType) { @@ -243,6 +245,8 @@ class PairingView extends GetView { case ErrorType.noClassicDevice: case ErrorType.deviceNotMatch: return Icons.headphones_outlined; + case ErrorType.associationFailed: + return Icons.link_off; default: return Icons.error_outline; } @@ -307,6 +311,8 @@ class PairingView extends GetView { return '请先通过系统蓝牙连接DeapSound设备'; case PairingState.verifying: return '正在验证设备...'; + case PairingState.associating: + return '正在建立设备关联...'; case PairingState.waitingBle: return '请稍候,正在完成配对...'; case PairingState.completed: @@ -324,6 +330,8 @@ class PairingView extends GetView { return '请确保连接的是DeapSound设备'; case ErrorType.deviceBound: return '该设备已被其他账号绑定'; + case ErrorType.associationFailed: + return '设备关联失败,请重试'; case ErrorType.bleTimeout: return '扫描超时,请确保设备在附近'; case ErrorType.networkError: diff --git a/lib/modules/pairing/views/pairing_view_new.dart b/lib/modules/pairing/views/pairing_view_new.dart index 8ee96a7cc..eae654a1b 100644 --- a/lib/modules/pairing/views/pairing_view_new.dart +++ b/lib/modules/pairing/views/pairing_view_new.dart @@ -153,6 +153,11 @@ class PairingView extends GetView { iconColor = Colors.orange; break; + case PairingState.associating: + iconData = Icons.link; + iconColor = Colors.blue; + break; + case PairingState.waitingBle: iconData = Icons.sync; iconColor = Colors.blue;