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.
235 lines
6.6 KiB
235 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';
|
|
|
|
/// 蓝牙设备信息
|
|
class BluetoothDevice {
|
|
final String name;
|
|
final String address;
|
|
final String type;
|
|
|
|
BluetoothDevice({
|
|
required this.name,
|
|
required this.address,
|
|
required this.type
|
|
});
|
|
|
|
@override
|
|
String toString() => 'BluetoothDevice(name: $name, address: $address, type: $type)';
|
|
}
|
|
|
|
/// 经典蓝牙服务
|
|
class ClassicBluetoothService extends GetxService {
|
|
static ClassicBluetoothService get to => Get.find<ClassicBluetoothService>();
|
|
|
|
// 通道名称
|
|
final MethodChannel _channel = const MethodChannel('com.deep_voice.classic_bluetooth');
|
|
final EventChannel _eventChannel = const EventChannel('com.deep_voice.classic_bluetooth_events');
|
|
|
|
/// 当前连接的设备
|
|
final currentDevice = Rx<BluetoothDevice?>(null);
|
|
|
|
/// 已连接耳机设备列表
|
|
final connectedDevices = <BluetoothDevice>[].obs;
|
|
|
|
/// 蓝牙设备状态监听
|
|
StreamSubscription? _bluetoothStateListener;
|
|
|
|
/// 蓝牙开关状态
|
|
final bluetoothState = 'on'.obs;
|
|
|
|
/// 蓝牙是否可用
|
|
bool get isBluetoothOn => bluetoothState.value == 'on';
|
|
|
|
/// 服务是否已初始化
|
|
bool _isInitialized = false;
|
|
|
|
/// 初始化蓝牙服务 - 单一入口点
|
|
Future<bool> initialize() async {
|
|
if (_isInitialized) {
|
|
Logger.info('蓝牙服务已经初始化,跳过');
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
Logger.info('正在初始化蓝牙服务...');
|
|
|
|
// 启动蓝牙设备监控 - 这将调用原生代码中的initBluetooth
|
|
await _channel.invokeMethod('startBluetoothDeviceMonitoring');
|
|
|
|
// 设置事件监听
|
|
_setupBluetoothStateListener();
|
|
|
|
_isInitialized = true;
|
|
Logger.info('蓝牙服务初始化成功');
|
|
return true;
|
|
} catch (e) {
|
|
Logger.error('初始化蓝牙服务失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 检查蓝牙权限
|
|
Future<bool> checkPermissions() async {
|
|
// 检查蓝牙相关权限
|
|
Map<Permission, PermissionStatus> statuses = await [
|
|
Permission.bluetooth,
|
|
Permission.bluetoothConnect,
|
|
Permission.bluetoothScan,
|
|
].request();
|
|
|
|
return statuses[Permission.bluetoothConnect] == PermissionStatus.granted;
|
|
}
|
|
|
|
/// 刷新已连接的蓝牙耳机设备
|
|
Future<bool> refreshConnectedDevices() async {
|
|
// 确保服务已初始化
|
|
if (!_isInitialized && !(await initialize())) {
|
|
return false;
|
|
}
|
|
|
|
// 如果蓝牙未开启,无法获取设备
|
|
if (!isBluetoothOn) {
|
|
Logger.info('蓝牙未开启,无法获取设备');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
// 只获取耳机设备
|
|
final devices = await getConnectedHeadsetDevices();
|
|
|
|
// 更新设备列表
|
|
connectedDevices.value = devices;
|
|
|
|
// 更新当前设备
|
|
if (connectedDevices.isNotEmpty && currentDevice.value == null) {
|
|
currentDevice.value = connectedDevices.first;
|
|
}
|
|
|
|
return connectedDevices.isNotEmpty;
|
|
} catch (e) {
|
|
Logger.error('刷新已连接设备失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 获取已连接的耳机设备
|
|
Future<List<BluetoothDevice>> getConnectedHeadsetDevices() async {
|
|
try {
|
|
// 确保服务已初始化
|
|
if (!_isInitialized && !(await initialize())) {
|
|
return [];
|
|
}
|
|
|
|
final result = await _channel.invokeMethod('getConnectedHeadsetDevices');
|
|
|
|
if (result is List) {
|
|
return result.map((device) => BluetoothDevice(
|
|
name: device['name'] ?? '未知设备',
|
|
address: device['address'] ?? '',
|
|
type: 'headset'
|
|
)).toList();
|
|
}
|
|
|
|
return [];
|
|
} catch (e) {
|
|
Logger.error('获取已连接的耳机设备失败: $e');
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// 设置蓝牙状态监听
|
|
void _setupBluetoothStateListener() {
|
|
_bluetoothStateListener?.cancel();
|
|
|
|
_bluetoothStateListener = _eventChannel
|
|
.receiveBroadcastStream()
|
|
.listen((event) {
|
|
if (event is Map) {
|
|
final type = event['type'] as String?;
|
|
|
|
if (type == 'bluetoothStateChanged') {
|
|
final state = event['state'] as String?;
|
|
if (state != null) {
|
|
_handleBluetoothStateChange(state);
|
|
}
|
|
} else if (type == 'deviceConnected') {
|
|
_handleDeviceConnected(event);
|
|
} else if (type == 'deviceDisconnected') {
|
|
_handleDeviceDisconnected(event);
|
|
}
|
|
}
|
|
}, onError: (error) {
|
|
Logger.error('蓝牙状态监听错误: $error');
|
|
});
|
|
}
|
|
|
|
/// 处理设备连接事件
|
|
void _handleDeviceConnected(Map event) {
|
|
final deviceMap = event['device'] as Map?;
|
|
if (deviceMap != null && (deviceMap['type'] == 'headset' || deviceMap['type'] == 'unknown')) {
|
|
final device = BluetoothDevice(
|
|
name: deviceMap['name'] ?? '未知设备',
|
|
address: deviceMap['address'] ?? '',
|
|
type: deviceMap['type'] ?? 'unknown'
|
|
);
|
|
|
|
// 更新设备列表
|
|
if (!connectedDevices.any((d) => d.address == device.address)) {
|
|
connectedDevices.add(device);
|
|
}
|
|
|
|
// 更新当前设备
|
|
currentDevice.value = device;
|
|
|
|
Logger.info('设备已连接: ${device.name}');
|
|
}
|
|
}
|
|
|
|
/// 处理设备断开事件
|
|
void _handleDeviceDisconnected(Map event) {
|
|
final deviceMap = event['device'] as Map?;
|
|
if (deviceMap != null) {
|
|
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() {
|
|
// 取消蓝牙状态监听
|
|
_bluetoothStateListener?.cancel();
|
|
super.onClose();
|
|
}
|
|
}
|