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.
241 lines
7.3 KiB
241 lines
7.3 KiB
import 'package:app_settings/app_settings.dart';
|
|
import 'package:get/get.dart';
|
|
import 'dart:async';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import '../../../routes/app_routes.dart';
|
|
import '../../../data/services/classic_bluetooth_service.dart';
|
|
import '../../../core/utils/logger.dart';
|
|
import 'dart:io';
|
|
|
|
/// 配对控制器,负责显示已连接经典蓝牙设备和处理基本配对流程
|
|
class PairingController extends GetxController {
|
|
static PairingController get to => Get.find();
|
|
|
|
// 经典蓝牙服务
|
|
final ClassicBluetoothService _bluetoothService = Get.find<ClassicBluetoothService>();
|
|
|
|
// 状态标志
|
|
final isLoading = false.obs;
|
|
|
|
// 权限是否已授予
|
|
final _hasPermissions = false.obs;
|
|
bool get hasPermissions => _hasPermissions.value;
|
|
|
|
// 蓝牙服务是否可用
|
|
final _isBluetoothServiceAvailable = true.obs;
|
|
bool get isBluetoothServiceAvailable => _isBluetoothServiceAvailable.value;
|
|
|
|
// 状态描述(用于UI显示)
|
|
final statusDescription = 'initializing'.tr.obs;
|
|
|
|
// 是否正在跳转到主页
|
|
bool _isNavigatingToHome = false;
|
|
|
|
// 当前连接设备和设备列表(直接从服务获取)
|
|
Rx<BluetoothDevice?> get currentDevice => _bluetoothService.currentDevice;
|
|
RxList<BluetoothDevice> get connectedDevices => _bluetoothService.connectedDevices;
|
|
RxString get bluetoothState => _bluetoothService.bluetoothState;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
_initialize();
|
|
}
|
|
|
|
/// 初始化流程
|
|
Future<void> _initialize() async {
|
|
try {
|
|
isLoading.value = true;
|
|
statusDescription.value = 'checkingPermissions'.tr;
|
|
|
|
// 检查并请求权限
|
|
if (!await _checkAndRequestPermissions()) {
|
|
statusDescription.value = 'permissionDenied'.tr;
|
|
return;
|
|
}
|
|
|
|
statusDescription.value = 'initializing'.tr;
|
|
|
|
// 初始化蓝牙服务
|
|
if (!await _bluetoothService.initialize()) {
|
|
Logger.error('蓝牙服务初始化失败');
|
|
statusDescription.value = 'bluetoothInitializationFailure'.tr;
|
|
_isBluetoothServiceAvailable.value = false;
|
|
return;
|
|
}
|
|
|
|
// 设置状态监听
|
|
_setupStatusListeners();
|
|
|
|
// 刷新已连接设备
|
|
statusDescription.value = 'searchingDevice'.tr;
|
|
await refreshConnectedDevices();
|
|
} catch (e) {
|
|
Logger.error('初始化配对控制器失败: $e');
|
|
statusDescription.value = 'initializationFailure'.tr;
|
|
_isBluetoothServiceAvailable.value = false;
|
|
} finally {
|
|
isLoading.value = false;
|
|
if (hasPermissions) {
|
|
_updateStatusDescription();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 检查并请求必要的蓝牙权限
|
|
Future<bool> _checkAndRequestPermissions() async {
|
|
Map<Permission, PermissionStatus> statuses;
|
|
List<Permission> permissionsToRequest = [];
|
|
|
|
if (Platform.isAndroid) {
|
|
// Android 12+ (SDK 31+) 需要 SCAN 和 CONNECT
|
|
// Android 6+ (SDK 23+) 需要 LOCATION
|
|
permissionsToRequest.add(Permission.locationWhenInUse); // 基本定位权限
|
|
// Android 12及以上版本才需要请求蓝牙扫描和连接权限
|
|
if (await _getAndroidSdkVersion() >= 31) {
|
|
permissionsToRequest.add(Permission.bluetoothScan);
|
|
permissionsToRequest.add(Permission.bluetoothConnect);
|
|
}
|
|
} else if (Platform.isIOS) {
|
|
permissionsToRequest.add(Permission.bluetooth);
|
|
}
|
|
|
|
statuses = await permissionsToRequest.request();
|
|
|
|
bool allGranted = true;
|
|
statuses.forEach((permission, status) {
|
|
if (!status.isGranted) {
|
|
allGranted = false;
|
|
Logger.warning('权限 ${permission.toString()} 未被授予: $status');
|
|
}
|
|
});
|
|
|
|
_hasPermissions.value = allGranted;
|
|
return allGranted;
|
|
}
|
|
|
|
// 辅助方法获取Android SDK版本
|
|
Future<int> _getAndroidSdkVersion() async {
|
|
if (Platform.isAndroid) {
|
|
// 这里需要原生代码支持来获取确切的SDK版本,
|
|
// 或者使用 device_info_plus 插件
|
|
// 暂时返回一个较高值以触发新权限请求,如果需要精确控制则需要引入插件
|
|
// 或者,如果你的minSdkVersion >= 31,可以直接请求新权限
|
|
// 假设minSdkVersion < 31,我们需要一种方式判断当前运行设备的SDK版本
|
|
// 为了简化,我们这里先假设需要请求新权限,如果你的目标SDK较低,需要调整
|
|
return 31; // 假设运行在需要新权限的设备上
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/// 设置状态变化监听
|
|
void _setupStatusListeners() {
|
|
// 监听蓝牙状态变化
|
|
ever(bluetoothState, (_) => _updateStatusDescription());
|
|
|
|
// 监听当前设备变化
|
|
ever(currentDevice, (device) {
|
|
_updateStatusDescription();
|
|
|
|
// 当设备连接时自动跳转
|
|
if (device != null) {
|
|
_autoNavigateToHome();
|
|
}
|
|
});
|
|
}
|
|
|
|
/// 更新状态描述
|
|
void _updateStatusDescription() {
|
|
if (!hasPermissions) {
|
|
statusDescription.value = 'permissionDenied'.tr;
|
|
return;
|
|
}
|
|
|
|
if (bluetoothState.value == 'off') {
|
|
statusDescription.value = 'bluetoothTurnedOff'.tr;
|
|
return;
|
|
}
|
|
|
|
if (currentDevice.value != null) {
|
|
statusDescription.value = '${'connectedDevice'.tr} ${currentDevice.value!.name}';
|
|
return;
|
|
}
|
|
|
|
if (connectedDevices.isNotEmpty) {
|
|
statusDescription.value = '${'findConnectedDevice'.tr} ${connectedDevices.first.name}';
|
|
return;
|
|
}
|
|
|
|
if (isLoading.value) {
|
|
statusDescription.value = 'searchingDevice'.tr;
|
|
return;
|
|
}
|
|
|
|
statusDescription.value = 'notFound'.tr;
|
|
}
|
|
|
|
/// 刷新已连接设备
|
|
Future<void> refreshConnectedDevices() async {
|
|
if (!_isBluetoothServiceAvailable.value) return;
|
|
|
|
if (!await _checkAndRequestPermissions()) {
|
|
statusDescription.value = 'permissionDenied'.tr;
|
|
return;
|
|
}
|
|
|
|
try {
|
|
isLoading.value = true;
|
|
statusDescription.value = 'searchingDevice'.tr;
|
|
|
|
await _bluetoothService.refreshConnectedDevices();
|
|
} catch (e) {
|
|
Logger.error('刷新设备失败: $e');
|
|
statusDescription.value = 'failedRefreshDevice'.tr;
|
|
} finally {
|
|
isLoading.value = false;
|
|
if (hasPermissions) {
|
|
_updateStatusDescription();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 自动跳转到主页
|
|
void _autoNavigateToHome() {
|
|
if (_isNavigatingToHome || currentDevice.value == null) return;
|
|
|
|
_isNavigatingToHome = true;
|
|
Logger.info('已找到连接的设备 ${currentDevice.value?.name},自动跳转到主页');
|
|
|
|
Future.delayed(const Duration(milliseconds: 500), () {
|
|
Get.offAllNamed(Routes.home);
|
|
});
|
|
}
|
|
|
|
/// 打开系统蓝牙设置
|
|
void openBluetoothSettings() {
|
|
try {
|
|
if (!hasPermissions) {
|
|
openAppSettings();
|
|
} else if (Platform.isAndroid && bluetoothState.value == 'off') {
|
|
AppSettings.openAppSettings(type: AppSettingsType.bluetooth);
|
|
} else if (Platform.isIOS) {
|
|
openAppSettings();
|
|
} else {
|
|
AppSettings.openAppSettings(type: AppSettingsType.bluetooth);
|
|
}
|
|
} catch (e) {
|
|
Logger.error('打开设置失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 打开应用设置
|
|
Future<void> openAppSettings() async {
|
|
await AppSettings.openAppSettings();
|
|
}
|
|
|
|
/// 跳过连接
|
|
void skipConnecting() {
|
|
_isNavigatingToHome = true;
|
|
Get.offAllNamed(Routes.home);
|
|
}
|
|
}
|
|
|