You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
9.1 KiB

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';
/// 蓝牙设备服务,用于发现和管理蓝牙设备
class BluetoothService extends GetxService {
static BluetoothService get to => Get.find<BluetoothService>();
// 单例实例
static final BluetoothService _instance = BluetoothService._internal();
factory BluetoothService() => _instance;
BluetoothService._internal();
// 设备状态
final _isAvailable = false.obs;
final _isOn = false.obs;
// 已连接的设备
final _connectedDevices = <BluetoothDevice>[].obs;
// 扫描状态
final _isScanning = false.obs;
// 扫描结果
final _scanResults = <ScanResult>[].obs;
// 当前选中的设备
final _selectedDevice = Rx<BluetoothDevice?>(null);
// 连接状态
final _connectionState = Rx<BluetoothConnectionState>(BluetoothConnectionState.disconnected);
// 订阅
StreamSubscription? _stateSubscription;
StreamSubscription? _scanSubscription;
StreamSubscription? _connectionSubscription;
// 权限状态
final _permissionsGranted = false.obs;
bool get permissionsGranted => _permissionsGranted.value;
// Getters
bool get isAvailable => _isAvailable.value;
bool get isOn => _isOn.value;
bool get isScanning => _isScanning.value;
List<BluetoothDevice> get connectedDevices => _connectedDevices;
List<ScanResult> get scanResults => _scanResults;
BluetoothDevice? get selectedDevice => _selectedDevice.value;
BluetoothConnectionState get connectionState => _connectionState.value;
// Observable getters (for reactive programming)
RxBool get isAvailableObs => _isAvailable;
RxBool get isOnObs => _isOn;
RxList<BluetoothDevice> get connectedDevicesObs => _connectedDevices;
RxList<ScanResult> get scanResultsObs => _scanResults;
Rx<BluetoothDevice?> get selectedDeviceObs => _selectedDevice;
Rx<BluetoothConnectionState> get connectionStateObs => _connectionState;
/// 初始化蓝牙服务
Future<BluetoothService> init() async {
try {
// 不在初始化时检查权限,改为在需要时才检查
// await _checkAndRequestPermissions();
// 监听蓝牙状态
_stateSubscription = FlutterBluePlus.adapterState.listen((state) {
_isOn.value = state == BluetoothAdapterState.on;
_isAvailable.value = state != BluetoothAdapterState.unavailable;
if (state == BluetoothAdapterState.on) {
// 蓝牙打开时,获取已连接设备,但不请求权限
// 只有在用户主动扫描时才请求权限
_getConnectedDevices();
} else if (state == BluetoothAdapterState.off) {
// 蓝牙关闭时,清空设备列表
_connectedDevices.clear();
_scanResults.clear();
_selectedDevice.value = null;
}
});
// 检查当前蓝牙状态,如果已开启则获取设备
if (await FlutterBluePlus.isOn) {
_isOn.value = true;
_isAvailable.value = true;
_getConnectedDevices();
}
return this;
} catch (e) {
Logger.error('初始化蓝牙服务失败: $e');
return this;
}
}
/// 检查并请求蓝牙所需权限
Future<bool> _checkAndRequestPermissions() async {
// 暂时跳过权限检查,直接返回true
_permissionsGranted.value = true;
return true;
}
/// 再次请求权限
Future<bool> requestPermissions() async {
// 暂时跳过权限检查,直接返回true
_permissionsGranted.value = true;
return true;
}
/// 获取已连接的设备
Future<void> _getConnectedDevices() async {
try {
// 获取已连接的设备
List<BluetoothDevice> devices = await FlutterBluePlus.connectedSystemDevices;
_connectedDevices.value = devices;
// 如果有已连接的设备但没有选中设备,则选中第一个
if (_connectedDevices.isNotEmpty && _selectedDevice.value == null) {
_selectedDevice.value = _connectedDevices[0];
_monitorConnectionState(_selectedDevice.value!);
}
Logger.info('已连接设备数量: ${_connectedDevices.length}');
} catch (e) {
Logger.error('获取已连接设备失败: $e');
}
}
/// 获取系统中已配对的设备
Future<List<BluetoothDevice>> getPairedDevices() async {
try {
// 获取已配对的设备(系统已知设备)
List<BluetoothDevice> systemDevices = await FlutterBluePlus.bondedDevices;
return systemDevices;
} catch (e) {
Logger.error('获取已配对设备失败: $e');
return [];
}
}
/// 开始扫描附近的蓝牙设备
Future<void> startScan({Duration? timeout}) async {
if (_isScanning.value) return;
// 清空旧的扫描结果
_scanResults.clear();
try {
// 开始扫描
_scanSubscription?.cancel();
_scanSubscription = FlutterBluePlus.scanResults.listen((results) {
_scanResults.value = results;
});
// 设置扫描中状态
_isScanning.value = true;
// 开始扫描
await FlutterBluePlus.startScan(
timeout: timeout ?? const Duration(seconds: 10),
);
// 扫描完成后更新状态
_isScanning.value = false;
Logger.info('蓝牙扫描完成,发现 ${_scanResults.length} 个设备');
} catch (e) {
_isScanning.value = false;
Logger.error('蓝牙扫描失败: $e');
}
}
/// 停止扫描
Future<void> stopScan() async {
if (!_isScanning.value) return;
try {
await FlutterBluePlus.stopScan();
_isScanning.value = false;
} catch (e) {
Logger.error('停止蓝牙扫描失败: $e');
}
}
/// 连接到指定设备
Future<bool> connectToDevice(BluetoothDevice device) async {
if (_selectedDevice.value == device) {
// 如果是当前选中设备,检查连接状态
if (_connectionState.value == BluetoothConnectionState.connected) {
Logger.info('设备 ${device.platformName} 已经连接,无需重新连接');
return true;
}
}
try {
// 检查设备是否已连接
bool isAlreadyConnected = false;
// 检查设备连接状态
BluetoothConnectionState state = await device.connectionState.first;
if (state == BluetoothConnectionState.connected) {
Logger.info('设备 ${device.platformName} 已处于连接状态');
isAlreadyConnected = true;
}
// 如果设备已连接,直接更新状态而不尝试连接
if (isAlreadyConnected) {
// 断开当前跟踪的设备(如果有)
if (_selectedDevice.value != null && _selectedDevice.value != device) {
_connectionSubscription?.cancel();
}
// 更新状态
_selectedDevice.value = device;
_monitorConnectionState(device);
return true;
}
// 断开当前连接
await disconnectFromDevice();
// 连接新设备
await device.connect();
// 更新状态
_selectedDevice.value = device;
_monitorConnectionState(device);
return true;
} catch (e) {
Logger.error('连接蓝牙设备失败: $e');
return false;
}
}
/// 断开与当前设备的连接
Future<bool> disconnectFromDevice() async {
if (_selectedDevice.value == null) return true;
try {
await _selectedDevice.value!.disconnect();
_connectionSubscription?.cancel();
_connectionSubscription = null;
_selectedDevice.value = null;
return true;
} catch (e) {
Logger.error('断开蓝牙设备连接失败: $e');
return false;
}
}
/// 监控连接状态
void _monitorConnectionState(BluetoothDevice device) {
_connectionSubscription?.cancel();
_connectionSubscription = device.connectionState.listen((state) {
_connectionState.value = state;
if (state == BluetoothConnectionState.disconnected) {
_selectedDevice.value = null;
}
});
}
/// 获取已连接设备的信息
Map<String, dynamic> getConnectedDeviceInfo() {
if (_selectedDevice.value == null) {
return {
'connected': false,
'device': null,
};
}
return {
'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
}
};
}
@override
void onClose() {
_stateSubscription?.cancel();
_scanSubscription?.cancel();
_connectionSubscription?.cancel();
disconnectFromDevice();
super.onClose();
}
}