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.
243 lines
6.6 KiB
243 lines
6.6 KiB
import 'dart:async';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import '../../core/utils/logger.dart';
|
|
import 'dart:io';
|
|
|
|
/// 蓝牙设备信息
|
|
class BluetoothDevice {
|
|
final String name;
|
|
final String address;
|
|
final String type;
|
|
|
|
BluetoothDevice({
|
|
required this.name,
|
|
required this.address,
|
|
required this.type
|
|
});
|
|
|
|
factory BluetoothDevice.fromMap(Map<dynamic, dynamic> map) {
|
|
return BluetoothDevice(
|
|
name: map['name'] ?? '未知设备',
|
|
address: map['address'] ?? '',
|
|
type: map['type'] ?? 'unknown',
|
|
);
|
|
}
|
|
|
|
@override
|
|
String toString() => 'BluetoothDevice(name: $name, address: $address, type: $type)';
|
|
}
|
|
|
|
/// 经典蓝牙服务
|
|
/// 负责经典蓝牙设备的连接状态管理
|
|
class ClassicBluetoothService extends GetxService {
|
|
static ClassicBluetoothService get to => Get.find<ClassicBluetoothService>();
|
|
|
|
// 通道名称
|
|
final _methodChannel = const MethodChannel('com.yunqiinnovation.classic_bluetooth/methods');
|
|
final _eventChannel = const EventChannel('com.yunqiinnovation.classic_bluetooth/events');
|
|
|
|
/// 当前连接的设备
|
|
final currentDevice = Rx<BluetoothDevice?>(null);
|
|
|
|
/// 已连接耳机设备列表
|
|
final connectedDevices = <BluetoothDevice>[].obs;
|
|
|
|
/// 蓝牙事件监听
|
|
StreamSubscription? _eventSubscription;
|
|
|
|
/// 蓝牙开关状态
|
|
final bluetoothState = 'unknown'.obs;
|
|
|
|
/// 蓝牙是否可用
|
|
bool get isBluetoothEnabled => bluetoothState.value == 'on';
|
|
|
|
/// 服务是否已初始化
|
|
bool _isInitialized = false;
|
|
|
|
/// 初始化蓝牙服务
|
|
Future<bool> initialize() async {
|
|
if (_isInitialized) {
|
|
Logger.info('蓝牙服务已经初始化,跳过');
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
Logger.info('正在初始化蓝牙服务...');
|
|
|
|
// 检查蓝牙是否启用
|
|
final bool isEnabled = await _methodChannel.invokeMethod<bool>('isBluetoothEnabled') ?? false;
|
|
bluetoothState.value = isEnabled ? 'on' : 'off';
|
|
Logger.info('初始蓝牙状态: ${bluetoothState.value}');
|
|
|
|
// 设置事件监听
|
|
_setupEventListener();
|
|
|
|
_isInitialized = true;
|
|
Logger.info('蓝牙服务初始化成功');
|
|
|
|
// 如果蓝牙已启用,自动获取已连接设备
|
|
if (isEnabled) {
|
|
await refreshConnectedDevices();
|
|
}
|
|
|
|
return true;
|
|
} catch (e) {
|
|
Logger.error('初始化蓝牙服务失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 设置事件监听
|
|
void _setupEventListener() {
|
|
_eventSubscription?.cancel();
|
|
_eventSubscription = _eventChannel.receiveBroadcastStream().listen((event) {
|
|
if (event is Map) {
|
|
Logger.info('收到蓝牙事件: $event');
|
|
|
|
// 根据事件类型处理
|
|
final type = event['type'] as String?;
|
|
if (type == 'stateChanged') {
|
|
final state = event['state'] as String?;
|
|
if (state != null) {
|
|
_handleBluetoothStateChange(state);
|
|
}
|
|
} else if (type == 'deviceConnected') {
|
|
final deviceMap = event['device'] as Map?;
|
|
if (deviceMap != null) {
|
|
_handleDeviceConnected(deviceMap);
|
|
}
|
|
} else if (type == 'deviceDisconnected') {
|
|
final deviceMap = event['device'] as Map?;
|
|
if (deviceMap != null) {
|
|
_handleDeviceDisconnected(deviceMap);
|
|
}
|
|
}
|
|
}
|
|
}, onError: (e) {
|
|
Logger.error('蓝牙事件监听错误: $e');
|
|
});
|
|
}
|
|
|
|
|
|
/// 刷新已连接的蓝牙设备
|
|
Future<bool> refreshConnectedDevices() async {
|
|
// 确保服务已初始化
|
|
if (!_isInitialized && !(await initialize())) {
|
|
return false;
|
|
}
|
|
|
|
// 如果蓝牙未启用,无法获取设备
|
|
if (!isBluetoothEnabled) {
|
|
Logger.info('蓝牙未启用,无法获取设备');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
// 获取已连接的设备
|
|
final devices = await getConnectedDevices();
|
|
|
|
// 更新设备列表
|
|
connectedDevices.value = devices;
|
|
|
|
// 如果列表不为空且当前无选定设备,选择第一个
|
|
if (devices.isNotEmpty && currentDevice.value == null) {
|
|
currentDevice.value = devices.first;
|
|
}
|
|
|
|
return devices.isNotEmpty;
|
|
} catch (e) {
|
|
Logger.error('刷新已连接设备失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 获取已连接的蓝牙设备
|
|
Future<List<BluetoothDevice>> getConnectedDevices() async {
|
|
try {
|
|
// 确保服务已初始化
|
|
if (!_isInitialized && !(await initialize())) {
|
|
return [];
|
|
}
|
|
|
|
final result = await _methodChannel.invokeMethod('getConnectedDevices');
|
|
|
|
if (result is List) {
|
|
return result.map((device) => BluetoothDevice.fromMap(device)).toList();
|
|
}
|
|
|
|
return [];
|
|
} catch (e) {
|
|
Logger.error('获取已连接设备失败: $e');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// 检查蓝牙是否已开启
|
|
Future<bool> checkBluetoothEnabled() async {
|
|
try {
|
|
return await _methodChannel.invokeMethod<bool>('isBluetoothEnabled') ?? false;
|
|
} catch (e) {
|
|
Logger.error('检查蓝牙状态失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 处理设备连接事件
|
|
void _handleDeviceConnected(Map deviceMap) {
|
|
final device = BluetoothDevice.fromMap(deviceMap);
|
|
|
|
// 更新设备列表
|
|
if (!connectedDevices.any((d) => d.address == device.address)) {
|
|
connectedDevices.add(device);
|
|
}
|
|
|
|
// 更新当前设备
|
|
currentDevice.value = device;
|
|
|
|
Logger.info('设备已连接: ${device.name}');
|
|
}
|
|
|
|
/// 处理设备断开事件
|
|
void _handleDeviceDisconnected(Map deviceMap) {
|
|
final address = deviceMap['address'] as String?;
|
|
|
|
if (address != null) {
|
|
// 更新设备列表
|
|
connectedDevices.removeWhere((d) => d.address == address);
|
|
|
|
// 如果是当前设备,清除当前设备
|
|
if (currentDevice.value?.address == address) {
|
|
currentDevice.value = connectedDevices.isEmpty ? null : connectedDevices.first;
|
|
Logger.info('当前设备已断开连接');
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 处理蓝牙状态变化
|
|
void _handleBluetoothStateChange(String state) {
|
|
Logger.info('蓝牙状态变化: $state');
|
|
|
|
// 更新蓝牙状态
|
|
bluetoothState.value = state;
|
|
|
|
if (state == 'off') {
|
|
// 蓝牙关闭,清空设备信息
|
|
connectedDevices.clear();
|
|
currentDevice.value = null;
|
|
} else if (state == 'on') {
|
|
// 蓝牙重新开启,延迟一小段时间后刷新设备
|
|
Future.delayed(const Duration(milliseconds: 1000), () {
|
|
refreshConnectedDevices();
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
// 取消事件监听
|
|
_eventSubscription?.cancel();
|
|
super.onClose();
|
|
}
|
|
}
|
|
|