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.

247 lines
7.5 KiB

import 'dart:async';
import 'package:get/get.dart';
import '../../../core/routes/app_routes.dart';
import '../../../data/services/bluetooth_service.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart' hide BluetoothService;
import '../../../core/utils/logger.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/material.dart';
enum SearchStatus {
searching, // 正在搜索设备
found, // 找到设备
failed, // 搜索失败
noPermission, // 缺少权限
}
class PairingController extends GetxController {
// 搜索状态
final _searchStatus = SearchStatus.searching.obs;
SearchStatus get searchStatus => _searchStatus.value;
// 搜索动画的点
final _searchDots = ''.obs;
String get searchDots => _searchDots.value;
// 动画定时器
Timer? _animationTimer;
// 蓝牙服务
late BluetoothService _bluetoothService;
// 设备信息
final _deviceInfo = Rx<Map<String, dynamic>>({});
Map<String, dynamic> get deviceInfo => _deviceInfo.value;
// 蓝牙状态
final _isBluetoothAvailable = false.obs;
final _isBluetoothOn = false.obs;
bool get isBluetoothAvailable => _isBluetoothAvailable.value;
bool get isBluetoothOn => _isBluetoothOn.value;
// 错误消息
final _errorMessage = ''.obs;
String get errorMessage => _errorMessage.value;
@override
void onInit() {
super.onInit();
// 启动搜索动画
_startSearchingAnimation();
// 延迟更久初始化蓝牙服务,避免在应用启动时就请求权限和阻塞主线程
// 改为延迟初始化,给UI足够时间渲染
Future.delayed(const Duration(milliseconds: 1500), () {
_initBluetoothService();
});
}
@override
void onClose() {
_stopSearchingAnimation();
super.onClose();
}
// 初始化蓝牙服务
Future<void> _initBluetoothService() async {
try {
// 获取蓝牙服务实例
if (Get.isRegistered<BluetoothService>()) {
_bluetoothService = Get.find<BluetoothService>();
} else {
// 在后台初始化蓝牙服务
_bluetoothService = await Get.put(BluetoothService()).init();
}
// 监听蓝牙状态变化
ever(_bluetoothService.isAvailableObs, (bool available) {
_isBluetoothAvailable.value = available;
});
ever(_bluetoothService.isOnObs, (bool on) {
_isBluetoothOn.value = on;
// 如果蓝牙开启,开始扫描设备
if (on) {
// 延迟开始扫描,避免权限请求过早和主线程阻塞
Future.delayed(const Duration(milliseconds: 800), () {
_startScanningDevices();
});
} else {
_errorMessage.value = '请打开蓝牙以搜索设备';
_searchStatus.value = SearchStatus.failed;
_stopSearchingAnimation();
}
});
// 如果蓝牙已经开启,直接开始扫描
if (_bluetoothService.isOn) {
_isBluetoothOn.value = true;
// 延迟开始扫描,避免权限请求过早和主线程阻塞
Future.delayed(const Duration(milliseconds: 800), () {
_startScanningDevices();
});
} else {
_errorMessage.value = '请打开蓝牙以搜索设备';
}
} catch (e) {
Logger.error('初始化蓝牙服务失败: $e');
_errorMessage.value = '初始化蓝牙服务失败';
_searchStatus.value = SearchStatus.failed;
_stopSearchingAnimation();
}
}
// 启动搜索动画
void _startSearchingAnimation() {
_stopSearchingAnimation(); // 清除已有的定时器
int count = 0;
_animationTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) {
count = (count + 1) % 4;
_searchDots.value = '.' * count;
});
}
// 停止搜索动画
void _stopSearchingAnimation() {
_animationTimer?.cancel();
_animationTimer = null;
_searchDots.value = '';
}
// 请求必要权限
Future<bool> _requestPermissions() async {
// 暂时跳过权限检查,直接返回true
return true;
}
// 打开应用设置
void goToAppSettings() async {
try {
await openAppSettings();
} catch (e) {
Logger.error('打开应用设置失败: $e');
Get.snackbar(
'提示',
'无法打开应用设置,请手动打开系统设置授予权限',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red[100],
colorText: Colors.red[800],
duration: const Duration(seconds: 3),
);
}
}
// 开始扫描蓝牙设备
Future<void> _startScanningDevices() async {
try {
_searchStatus.value = SearchStatus.searching;
// 先检查是否有上次连接的设备信息
if (_bluetoothService.lastConnectedDeviceInfo.isNotEmpty &&
_bluetoothService.lastConnectedDeviceInfo['connected'] == true) {
Logger.info('使用上次连接的设备信息');
_deviceInfo.value = _bluetoothService.lastConnectedDeviceInfo;
_onDeviceFound();
return;
}
// 使用BluetoothService的自动连接功能查找设备
Logger.info('尝试自动连接设备');
BluetoothDevice? device = await _bluetoothService.autoConnectDevice()
.timeout(const Duration(seconds: 8), onTimeout: () {
Logger.info('自动连接设备超时');
return null;
});
if (device != null) {
Logger.info('自动连接设备成功: ${device.platformName}');
_deviceInfo.value = _bluetoothService.getConnectedDeviceInfo();
_onDeviceFound();
return;
}
// 如果自动连接失败,尝试扫描新设备
Logger.info('自动连接失败,开始扫描新设备');
device = await _bluetoothService.scanAndConnectToDevice(
timeout: const Duration(seconds: 5)
).timeout(const Duration(seconds: 6), onTimeout: () {
Logger.info('扫描并连接设备超时');
return null;
});
if (device != null) {
Logger.info('扫描并连接设备成功: ${device.platformName}');
_deviceInfo.value = _bluetoothService.getConnectedDeviceInfo();
_onDeviceFound();
} else {
// 未找到任何设备
_errorMessage.value = '未找到蓝牙设备,请确保设备已开启并在附近';
_searchStatus.value = SearchStatus.failed;
_stopSearchingAnimation();
}
} catch (e) {
Logger.error('设备搜索和连接失败: $e');
_errorMessage.value = '设备搜索失败: ${e.toString()}';
_searchStatus.value = SearchStatus.failed;
_stopSearchingAnimation();
}
}
// 设备找到并连接成功后的处理
void _onDeviceFound() {
_searchStatus.value = SearchStatus.found;
_stopSearchingAnimation();
// 更新日志并延迟跳转到主页
Logger.info('设备连接成功,准备跳转到主页');
Timer(const Duration(seconds: 1), () {
Get.offAllNamed(Routes.home, arguments: _deviceInfo.value);
});
}
// 手动连接
void manualConnect() {
// 停止当前扫描(如果有)
_bluetoothService.stopScan();
// 更新UI状态
_startSearchingAnimation();
_searchStatus.value = SearchStatus.searching;
_errorMessage.value = '';
// 直接开始扫描并连接
_startScanningDevices();
}
// 稍后再说
void skipConnecting() {
// 停止当前扫描
_bluetoothService.stopScan();
_stopSearchingAnimation();
// 直接跳转到主页
Get.offAllNamed(Routes.home);
}
}