import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; import 'package:get/get.dart'; import '../../core/utils/logger.dart'; import 'dart:io' show Platform; import 'package:permission_handler/permission_handler.dart'; /// 设备类型枚举 enum DeviceType { unknown, // 未知设备类型 classicAudio, // 经典蓝牙音频设备(耳机等) ble, // BLE设备 dual // 双模设备(同时支持经典蓝牙和BLE) } /// 蓝牙设备服务,用于发现和管理蓝牙设备 class BluetoothService extends GetxService { static BluetoothService get to => Get.find(); // 内部实例 BluetoothService._internal(); static final BluetoothService _instance = BluetoothService._internal(); factory BluetoothService() => _instance; // ====== 状态管理 ====== // 蓝牙适配器状态 final _isAvailable = false.obs; final _isOn = false.obs; final _isInitialized = false.obs; // 操作状态 final _isScanning = false.obs; final _permissionsGranted = false.obs; // 设备管理 final _connectedDevices = [].obs; final _systemPairedDevices = [].obs; final _scanResults = [].obs; final _selectedDevice = Rx(null); final _deviceType = Rx(DeviceType.unknown); final _connectionState = Rx(BluetoothConnectionState.disconnected); final _lastConnectedDeviceInfo = Rx>({}); // 流订阅 StreamSubscription? _stateSubscription; StreamSubscription? _scanSubscription; StreamSubscription? _connectionSubscription; // ====== Getters ====== // 基本getter bool get isAvailable => _isAvailable.value; bool get isOn => _isOn.value; bool get isInitialized => _isInitialized.value; bool get isScanning => _isScanning.value; bool get permissionsGranted => _permissionsGranted.value; // 设备相关getter List get connectedDevices => _connectedDevices; List get systemPairedDevices => _systemPairedDevices; List get scanResults => _scanResults; BluetoothDevice? get selectedDevice => _selectedDevice.value; DeviceType get deviceType => _deviceType.value; BluetoothConnectionState get connectionState => _connectionState.value; Map get lastConnectedDeviceInfo => _lastConnectedDeviceInfo.value; // Observable getters RxBool get isAvailableObs => _isAvailable; RxBool get isOnObs => _isOn; RxBool get isInitializedObs => _isInitialized; RxBool get isScanningObs => _isScanning; RxBool get permissionsGrantedObs => _permissionsGranted; RxList get connectedDevicesObs => _connectedDevices; RxList get scanResultsObs => _scanResults; Rx get selectedDeviceObs => _selectedDevice; Rx get deviceTypeObs => _deviceType; Rx get connectionStateObs => _connectionState; Rx> get lastConnectedDeviceInfoObs => _lastConnectedDeviceInfo; /// 初始化蓝牙服务 Future init() async { if (_isInitialized.value) { Logger.info('蓝牙服务已初始化,无需重复初始化'); return this; } Logger.info('开始初始化蓝牙服务'); try { // 1. 设置蓝牙状态监听 _setupBluetoothListeners(); // 2. 初始检查蓝牙状态 _checkBluetoothState(); // 3. 标记初始化完成 _isInitialized.value = true; Logger.info('蓝牙服务初始化完成'); return this; } catch (e) { Logger.error('初始化蓝牙服务失败: $e'); return this; } } /// 设置蓝牙状态监听 void _setupBluetoothListeners() { // 取消旧订阅(如果有) _stateSubscription?.cancel(); // 监听蓝牙适配器状态变化 _stateSubscription = FlutterBluePlus.adapterState.listen((state) { _isOn.value = state == BluetoothAdapterState.on; _isAvailable.value = state != BluetoothAdapterState.unavailable; if (state == BluetoothAdapterState.on) { Logger.info('蓝牙已开启'); if (_permissionsGranted.value) { _refreshSystemDevices(); } } else if (state == BluetoothAdapterState.off) { Logger.info('蓝牙已关闭'); _resetDeviceState(); } }); } /// 初始检查蓝牙状态 Future _checkBluetoothState() async { try { bool isOn = await FlutterBluePlus.isOn .timeout(const Duration(seconds: 5), onTimeout: () => false); _isOn.value = isOn; _isAvailable.value = isOn; Logger.info('当前蓝牙是否已开启: $isOn'); } catch (e) { Logger.error('检查蓝牙状态失败: $e'); _isOn.value = false; _isAvailable.value = false; } } /// 重置设备状态 void _resetDeviceState() { _connectedDevices.clear(); _systemPairedDevices.clear(); _scanResults.clear(); _selectedDevice.value = null; _lastConnectedDeviceInfo.value = {}; _deviceType.value = DeviceType.unknown; // 取消正在进行的操作 _scanSubscription?.cancel(); _connectionSubscription?.cancel(); _isScanning.value = false; } /// 检查并请求蓝牙权限 Future requestPermissions() async { try { // iOS无需额外权限 if (!Platform.isAndroid) { _permissionsGranted.value = true; return true; } // 请求所有必要权限 final permissions = [ Permission.bluetoothScan, Permission.bluetoothConnect, Permission.location, // Android需要定位权限来扫描BLE设备 Permission.microphone ]; // 一次性请求所有权限 Map statuses = await permissions.request(); // 检查所有权限是否已授予 bool allGranted = statuses.values.every((status) => status.isGranted); _permissionsGranted.value = allGranted; if (!allGranted) { // 检查哪些权限被拒绝 List deniedPermissions = []; statuses.forEach((permission, status) { if (!status.isGranted) { deniedPermissions.add(permission.toString().split('.').last); } }); Logger.warning('权限被拒绝: ${deniedPermissions.join(", ")}'); } return allGranted; } catch (e) { Logger.error('请求权限失败: $e'); _permissionsGranted.value = false; return false; } } /// 刷新系统蓝牙设备(已连接和已配对) Future _refreshSystemDevices() async { if (!_permissionsGranted.value || !_isOn.value) { Logger.warning('无法刷新系统设备:蓝牙未开启或缺少权限'); return; } try { // 获取已连接的系统设备 List devices = await FlutterBluePlus.connectedSystemDevices .timeout(const Duration(seconds: 10), onTimeout: () => []); _connectedDevices.value = devices; Logger.info('获取到${devices.length}个系统已连接设备'); // 更新选中设备的连接状态(如果有) if (_selectedDevice.value != null) { bool stillConnected = _connectedDevices.any( (d) => d.remoteId.str == _selectedDevice.value!.remoteId.str ); _connectionState.value = stillConnected ? BluetoothConnectionState.connected : BluetoothConnectionState.disconnected; if (stillConnected) { _updateLastConnectedDeviceInfo(); } } // 获取系统已配对设备 List pairedDevices = await FlutterBluePlus.bondedDevices .timeout(const Duration(seconds: 10), onTimeout: () => []); _systemPairedDevices.value = pairedDevices; Logger.info('获取到${pairedDevices.length}个系统已配对设备'); } catch (e) { Logger.error('刷新系统设备失败: $e'); } } /// 开始扫描附近的蓝牙设备 Future> startScan({Duration? timeout}) async { // 检查条件 if (!_permissionsGranted.value) { Logger.warning('缺少蓝牙扫描权限,无法扫描设备'); return []; } if (!_isOn.value) { Logger.warning('蓝牙未开启,无法扫描设备'); return []; } // 如果已经在扫描,先停止 if (_isScanning.value) { await stopScan(); } _scanResults.clear(); Logger.info('开始扫描附近蓝牙设备...'); try { // 设置结果监听 _scanSubscription?.cancel(); _scanSubscription = FlutterBluePlus.scanResults.listen((results) { _scanResults.value = results; }); // 开始扫描 _isScanning.value = true; await FlutterBluePlus.startScan( timeout: timeout ?? const Duration(seconds: 10), androidScanMode: AndroidScanMode.lowLatency, ); // 扫描完成 _isScanning.value = false; Logger.info('扫描完成,发现${_scanResults.length}个设备'); return _scanResults; } catch (e) { _isScanning.value = false; Logger.error('扫描设备失败: $e'); return []; } } /// 停止扫描 Future stopScan() async { if (!_isScanning.value) return; try { await FlutterBluePlus.stopScan(); _isScanning.value = false; Logger.info('已停止蓝牙扫描'); } catch (e) { Logger.error('停止扫描失败: $e'); } } /// 连接到指定蓝牙设备 Future connectToDevice(BluetoothDevice device) async { // 检查条件 if (!_permissionsGranted.value) { Logger.warning('缺少蓝牙连接权限,无法连接设备'); return false; } if (!_isOn.value) { Logger.warning('蓝牙未开启,无法连接设备'); return false; } Logger.info('尝试连接设备: ${device.platformName}'); try { // 确定设备类型 _determineDeviceType(device); // 检查设备是否已连接 bool alreadyConnected = _connectedDevices.any((d) => d.remoteId.str == device.remoteId.str); // 如果当前已选择该设备且已连接,则无需再连接 if (_selectedDevice.value == device && alreadyConnected) { Logger.info('设备已连接,无需重复连接'); _connectionState.value = BluetoothConnectionState.connected; _updateLastConnectedDeviceInfo(); return true; } // 如果已选择了其他设备,先断开 if (_selectedDevice.value != null && _selectedDevice.value != device) { await disconnectFromDevice(); } // 设置新的目标设备 _selectedDevice.value = device; // 针对不同类型设备采取不同连接策略 if (_deviceType.value == DeviceType.classicAudio) { // 经典蓝牙设备(如音频设备)依赖系统连接 return _connectToClassicAudioDevice(device); } else { // BLE设备直接通过库连接 return _connectToBLEDevice(device); } } catch (e) { Logger.error('连接设备过程中出错: $e'); _connectionState.value = BluetoothConnectionState.disconnected; return false; } } /// 连接经典蓝牙音频设备 Future _connectToClassicAudioDevice(BluetoothDevice device) async { Logger.info('尝试连接经典蓝牙音频设备'); try { // 刷新系统设备列表 await _refreshSystemDevices(); // 检查设备是否在系统已连接列表中 bool connected = _connectedDevices.any((d) => d.remoteId.str == device.remoteId.str); if (connected) { Logger.info('经典蓝牙设备已在系统连接列表中'); _connectionState.value = BluetoothConnectionState.connected; _updateLastConnectedDeviceInfo(); return true; } else { Logger.info('经典蓝牙设备未在系统连接列表中,需要在系统设置中进行配对'); _connectionState.value = BluetoothConnectionState.disconnected; return false; } } catch (e) { Logger.error('连接经典蓝牙设备失败: $e'); _connectionState.value = BluetoothConnectionState.disconnected; return false; } } /// 连接BLE设备 Future _connectToBLEDevice(BluetoothDevice device) async { Logger.info('尝试连接BLE设备'); _connectionState.value = BluetoothConnectionState.connecting; try { // 设置连接状态监听 _connectionSubscription?.cancel(); _connectionSubscription = device.connectionState.listen((state) { Logger.info('BLE连接状态变化: $state'); _connectionState.value = state; if (state == BluetoothConnectionState.connected) { _updateLastConnectedDeviceInfo(); } }); // 尝试连接 await device.connect( autoConnect: false, timeout: const Duration(seconds: 10) ); // 等待连接状态 final completer = Completer(); bool isCompleted = false; // 添加一个本地变量跟踪完成状态 // 检查当前状态 if (_connectionState.value == BluetoothConnectionState.connected) { completer.complete(true); isCompleted = true; } else { // 设置超时 Timer(const Duration(seconds: 12), () { if (!isCompleted) { // 使用本地变量而不是 completer.isCompleted Logger.warning('连接设备超时'); completer.complete(false); isCompleted = true; } }); } bool result = await completer.future; if (result) { Logger.info('BLE设备连接成功'); _updateLastConnectedDeviceInfo(); } else { Logger.warning('BLE设备连接失败'); // 尝试断开连接 await device.disconnect().catchError((_) {}); } return result; } catch (e) { Logger.error('连接BLE设备失败: $e'); _connectionState.value = BluetoothConnectionState.disconnected; // 尝试断开连接 try { await device.disconnect(); } catch (_) {} return false; } } /// 断开当前设备连接 Future disconnectFromDevice() async { // 没有已选择的设备 if (_selectedDevice.value == null) { return true; } // 取消连接状态监听 _connectionSubscription?.cancel(); _connectionSubscription = null; try { // 对BLE设备才需要执行断开操作 if (_deviceType.value != DeviceType.classicAudio) { await _selectedDevice.value!.disconnect(); } // 清除设备状态 _selectedDevice.value = null; _connectionState.value = BluetoothConnectionState.disconnected; return true; } catch (e) { Logger.error('断开设备连接失败: $e'); // 即使失败,也清除选中设备 _selectedDevice.value = null; _connectionState.value = BluetoothConnectionState.disconnected; return false; } } /// 查找系统已连接设备 Future findConnectedSystemDevice() async { if (!_permissionsGranted.value || !_isOn.value) { Logger.warning('蓝牙未开启或缺少权限,无法查找系统连接设备'); return null; } try { // 刷新系统设备列表 await _refreshSystemDevices(); if (_connectedDevices.isEmpty) { return null; } // 优先找出可能的音频设备 BluetoothDevice device = _findAudioDevice(_connectedDevices) ?? _connectedDevices.first; // 自动选择设备 _selectedDevice.value = device; _determineDeviceType(device); _connectionState.value = BluetoothConnectionState.connected; _updateLastConnectedDeviceInfo(); return device; } catch (e) { Logger.error('查找系统已连接设备失败: $e'); return null; } } /// 查找音频设备 BluetoothDevice? _findAudioDevice(List devices) { if (devices.isEmpty) return null; // 音频设备的可能名称关键词 final List audioKeywords = [ 'headphone', 'earphone', 'earbuds', 'headset', 'speaker', 'audio', '耳机', '音箱', '音响' ]; // 尝试匹配音频设备名称 for (BluetoothDevice device in devices) { String name = device.platformName.toLowerCase(); if (audioKeywords.any((keyword) => name.contains(keyword))) { return device; } } return null; } /// 确定设备类型 void _determineDeviceType(BluetoothDevice device) { final String deviceName = device.platformName.toLowerCase(); // 音频设备关键词 final List audioKeywords = [ 'headphone', 'earphone', 'earbuds', 'headset', 'speaker', 'audio', '耳机', '音箱', '音响' ]; bool hasAudioKeyword = audioKeywords.any((keyword) => deviceName.contains(keyword)); bool inConnectedList = _connectedDevices.any((d) => d.remoteId.str == device.remoteId.str); if (hasAudioKeyword || inConnectedList) { _deviceType.value = DeviceType.classicAudio; } else { _deviceType.value = DeviceType.ble; } } /// 获取已连接设备的信息 Map getConnectedDeviceInfo() { if (_selectedDevice.value == null) { return { 'connected': false, 'device': null, 'deviceType': _deviceType.value.toString().split('.').last }; } final deviceInfo = { 'connected': _connectionState.value == BluetoothConnectionState.connected, 'device': { 'name': _selectedDevice.value!.platformName.isEmpty ? '未命名设备' : _selectedDevice.value!.platformName, 'id': _selectedDevice.value!.remoteId.str, 'isConnected': _connectionState.value == BluetoothConnectionState.connected, 'rssi': _scanResults .firstWhereOrNull((r) => r.device.remoteId == _selectedDevice.value!.remoteId) ?.rssi }, 'deviceType': _deviceType.value.toString().split('.').last }; return deviceInfo; } /// 更新最后连接的设备信息 void _updateLastConnectedDeviceInfo() { if (_selectedDevice.value != null) { _lastConnectedDeviceInfo.value = getConnectedDeviceInfo(); } } /// 清理资源 @override void onClose() { // 取消所有订阅 _stateSubscription?.cancel(); _scanSubscription?.cancel(); _connectionSubscription?.cancel(); // 断开设备连接 disconnectFromDevice(); super.onClose(); } }