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.

444 lines
13 KiB

import 'dart:async';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.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)';
}
/// 蓝牙事件类型
enum BluetoothEventType {
/// 设备已连接
deviceConnected,
/// 设备已断开
deviceDisconnected,
/// 蓝牙状态改变(开启/关闭)
bluetoothStateChanged
}
/// 蓝牙连接状态事件
class BluetoothConnectionEvent {
/// 事件类型
final BluetoothEventType type;
/// 相关设备(可能为空,比如蓝牙状态改变事件)
final BluetoothDevice? device;
/// 蓝牙状态(仅适用于bluetoothStateChanged事件)
final String? state;
/// 事件发生时间戳
final int timestamp;
BluetoothConnectionEvent({
required this.type,
this.device,
this.state,
required this.timestamp,
});
factory BluetoothConnectionEvent.fromMap(Map<dynamic, dynamic> map) {
BluetoothEventType eventType;
switch (map['type']) {
case 'deviceConnected':
eventType = BluetoothEventType.deviceConnected;
break;
case 'deviceDisconnected':
eventType = BluetoothEventType.deviceDisconnected;
break;
case 'bluetoothStateChanged':
eventType = BluetoothEventType.bluetoothStateChanged;
break;
default:
throw ArgumentError('未知事件类型: ${map['type']}');
}
final deviceMap = map['device'] as Map<dynamic, dynamic>?;
final BluetoothDevice? device = deviceMap != null
? BluetoothDevice(
name: deviceMap['name'] ?? '未知设备',
address: deviceMap['address'] ?? '',
type: deviceMap['type'] ?? 'unknown'
)
: null;
return BluetoothConnectionEvent(
type: eventType,
device: device,
state: map['state'] as String?,
timestamp: map['timestamp'] as int? ?? DateTime.now().millisecondsSinceEpoch,
);
}
@override
String toString() {
switch (type) {
case BluetoothEventType.deviceConnected:
return '蓝牙设备已连接: ${device?.name}';
case BluetoothEventType.deviceDisconnected:
return '蓝牙设备已断开: ${device?.name}';
case BluetoothEventType.bluetoothStateChanged:
return '蓝牙状态改变: $state';
}
}
}
/// 经典蓝牙服务
class ClassicBluetoothService extends GetxService {
static ClassicBluetoothService get to => Get.find<ClassicBluetoothService>();
// 注意: MainActivity.kt中定义的通道名称为 com.deep_voice.classic_bluetooth
final MethodChannel _channel = const MethodChannel('com.deep_voice.classic_bluetooth');
final EventChannel _eventChannel = const EventChannel('com.deep_voice.classic_bluetooth_events');
/// 蓝牙事件流控制器
final _connectionEventController = StreamController<BluetoothConnectionEvent>.broadcast();
/// 蓝牙事件流
Stream<BluetoothConnectionEvent> get connectionEvents => _connectionEventController.stream;
/// 当前连接的设备
final currentDevice = Rx<BluetoothDevice?>(null);
/// 已连接设备列表
final connectedDevices = <BluetoothDevice>[].obs;
/// 蓝牙是否可用
final _isBluetoothEnabled = true.obs;
bool get isBluetoothEnabled => _isBluetoothEnabled.value;
/// 是否正在加载
final isLoading = false.obs;
/// 错误信息
final errorMessage = ''.obs;
/// 蓝牙状态变化事件流
StreamSubscription? _bluetoothStateListener;
/// 设备连接回调
final List<Function(BluetoothDevice)> _deviceConnectedCallbacks = [];
/// 设备断开回调
final List<Function(BluetoothDevice)> _deviceDisconnectedCallbacks = [];
/// 蓝牙状态变化回调
final List<Function(String)> _bluetoothStateChangedCallbacks = [];
/// 服务是否已初始化
bool _isInitialized = false;
ClassicBluetoothService() {
// 创建服务时不立即初始化,避免还没有原生支持时就调用方法
Logger.info('创建 ClassicBluetoothService 实例');
}
/// 初始化蓝牙服务
/// 必须在使用任何方法前调用此方法确保通道已设置
Future<bool> initialize() async {
if (_isInitialized) {
Logger.info('ClassicBluetoothService 已经初始化');
return true;
}
try {
Logger.info('正在初始化 ClassicBluetoothService...');
// 设置事件监听器
_setupBluetoothStateListener();
_isInitialized = true;
Logger.info('ClassicBluetoothService 初始化成功');
return true;
} catch (e) {
Logger.error('初始化 ClassicBluetoothService 失败: $e');
errorMessage.value = '初始化蓝牙服务失败';
return false;
}
}
/// 检查并请求蓝牙权限
Future<bool> checkAndRequestPermissions() async {
try {
// 首先确保服务已初始化
if (!_isInitialized && !(await initialize())) {
Logger.error('无法初始化蓝牙服务');
errorMessage.value = '无法初始化蓝牙服务';
return false;
}
// 检查蓝牙相关权限
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetooth,
Permission.bluetoothConnect,
Permission.bluetoothScan,
Permission.location,
Permission.microphone,
].request();
// 检查蓝牙连接权限
if (statuses[Permission.bluetoothConnect] != PermissionStatus.granted) {
Logger.error('蓝牙连接权限被拒绝');
errorMessage.value = '蓝牙连接权限被拒绝';
return false;
}
return true;
} catch (e) {
Logger.error('检查蓝牙权限失败: $e');
errorMessage.value = '检查蓝牙权限失败';
return false;
}
}
/// 刷新已连接的蓝牙设备
Future<bool> refreshConnectedDevices() async {
try {
// 首先确保服务已初始化
if (!_isInitialized && !(await initialize())) {
Logger.error('无法初始化蓝牙服务');
errorMessage.value = '无法初始化蓝牙服务';
return false;
}
errorMessage.value = '';
// 获取A2DP设备
final a2dpDevices = await getConnectedA2dpDevices();
Logger.info('已连接的A2DP设备: ${a2dpDevices.length}');
// 获取耳机设备
final headsetDevices = await getConnectedHeadsetDevices();
Logger.info('已连接的耳机设备: ${headsetDevices.length}');
// 更新设备列表
connectedDevices.value = [...a2dpDevices, ...headsetDevices];
// 更新当前设备
if (connectedDevices.isNotEmpty && currentDevice.value == null) {
currentDevice.value = connectedDevices.first;
}
return connectedDevices.isNotEmpty;
} catch (e) {
Logger.error('刷新已连接设备失败: $e');
errorMessage.value = '获取设备信息失败';
return false;
}
}
/// 获取已连接的A2DP设备(音频设备)
Future<List<BluetoothDevice>> getConnectedA2dpDevices() async {
try {
// 确保服务已初始化
if (!_isInitialized && !(await initialize())) {
Logger.error('无法初始化蓝牙服务');
return [];
}
final result = await _channel.invokeMethod('getConnectedA2dpDevices');
Logger.info('获取已连接的A2DP设备结果: $result');
if (result is List) {
final devices = result.map((device) => BluetoothDevice(
name: device['name'] ?? '未知设备',
address: device['address'] ?? '',
type: 'a2dp'
)).toList();
return devices;
}
return [];
} catch (e) {
Logger.error('获取已连接的A2DP设备失败: $e');
return [];
}
}
/// 获取已连接的耳机设备
Future<List<BluetoothDevice>> getConnectedHeadsetDevices() async {
try {
// 确保服务已初始化
if (!_isInitialized && !(await initialize())) {
Logger.error('无法初始化蓝牙服务');
return [];
}
final result = await _channel.invokeMethod('getConnectedHeadsetDevices');
Logger.info('获取已连接的耳机设备结果: $result');
if (result is List) {
final devices = result.map((device) => BluetoothDevice(
name: device['name'] ?? '未知设备',
address: device['address'] ?? '',
type: 'headset'
)).toList();
return devices;
}
return [];
} catch (e) {
Logger.error('获取已连接的耳机设备失败: $e');
return [];
}
}
/// 设置蓝牙状态监听
void _setupBluetoothStateListener() {
try {
_bluetoothStateListener = _eventChannel
.receiveBroadcastStream()
.listen((event) {
Logger.info('收到蓝牙事件: $event');
if (event is Map) {
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) {
final device = BluetoothDevice(
name: deviceMap['name'] ?? '未知设备',
address: deviceMap['address'] ?? '',
type: deviceMap['type'] ?? 'unknown'
);
_handleDeviceConnected(device);
}
} else if (type == 'deviceDisconnected') {
final deviceMap = event['device'] as Map?;
if (deviceMap != null) {
final device = BluetoothDevice(
name: deviceMap['name'] ?? '未知设备',
address: deviceMap['address'] ?? '',
type: deviceMap['type'] ?? 'unknown'
);
_handleDeviceDisconnected(device);
}
}
}
}, onError: (error) {
Logger.error('蓝牙状态监听错误: $error');
});
} catch (e) {
Logger.error('设置蓝牙状态监听失败: $e');
}
}
/// 处理蓝牙状态变化
void _handleBluetoothStateChange(String state) {
Logger.info('蓝牙状态变化: $state');
// 如果蓝牙关闭,清除设备信息
if (state == 'off') {
connectedDevices.clear();
currentDevice.value = null;
}
// 通知所有回调
for (var callback in _bluetoothStateChangedCallbacks) {
callback(state);
}
}
/// 处理设备连接
void _handleDeviceConnected(BluetoothDevice device) {
Logger.info('设备已连接: ${device.name}');
// 更新设备列表
if (!connectedDevices.any((d) => d.address == device.address)) {
connectedDevices.add(device);
}
// 更新当前设备
currentDevice.value = device;
// 通知所有回调
for (var callback in _deviceConnectedCallbacks) {
callback(device);
}
}
/// 处理设备断开
void _handleDeviceDisconnected(BluetoothDevice device) {
Logger.info('设备已断开: ${device.name}');
// 更新设备列表
connectedDevices.removeWhere((d) => d.address == device.address);
// 如果是当前设备,清除当前设备
if (currentDevice.value?.address == device.address) {
currentDevice.value = connectedDevices.isEmpty ? null : connectedDevices.first;
}
// 通知所有回调
for (var callback in _deviceDisconnectedCallbacks) {
callback(device);
}
}
/// 注册设备连接回调
void onDeviceConnected(Function(BluetoothDevice) callback) {
_deviceConnectedCallbacks.add(callback);
}
/// 注册设备断开回调
void onDeviceDisconnected(Function(BluetoothDevice) callback) {
_deviceDisconnectedCallbacks.add(callback);
}
/// 注册蓝牙状态变化回调
void onBluetoothStateChanged(Function(String) callback) {
_bluetoothStateChangedCallbacks.add(callback);
}
/// 打开蓝牙设置
Future<bool> openBluetoothSettings() async {
try {
await AppSettings.openAppSettings();
return true;
} catch (e) {
Logger.error('打开蓝牙设置失败: $e');
return false;
}
}
@override
void onClose() {
// 取消蓝牙状态监听
_bluetoothStateListener?.cancel();
// 清除回调
_deviceConnectedCallbacks.clear();
_deviceDisconnectedCallbacks.clear();
_bluetoothStateChangedCallbacks.clear();
super.onClose();
}
}