diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart index ca7cbd4e3..4fd99d91e 100644 --- a/lib/data/services/ble_manager.dart +++ b/lib/data/services/ble_manager.dart @@ -179,6 +179,19 @@ class BleManager extends GetxService { state == BleConnectionState.error) { Logger.info('BLE设备已断开或发生错误'); _isConnected.value = false; + // 更新设备信息 + _updateDeviceInfoIfNeeded( + batteryLevel: 0, + leftEarBattery: 0, + rightEarBattery: 0, + caseBattery: 0, + leftEarCharging: false, + rightEarCharging: false, + caseCharging: false, + firmwareVersion: '', + firmwareProductId: '', + firmwareProductColor: '', + ); } } diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 6a41a2b8b..8d0f3653b 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -40,7 +40,7 @@ class OtaUpgradeController extends GetxController { final isUpdateAvailable = true.obs; // 当前升级进度,范围为 0.0 到 1.0 - final RxDouble progress = 0.0.obs; + // final RxDouble progress = 0.0.obs; // OTA 单例实例,用于处理升级相关逻辑 final jlota = Ota.instance; @@ -52,7 +52,12 @@ class OtaUpgradeController extends GetxController { final _bleManager = Get.find(); final maxRetryAttempts = 3; // 最大重试次数 int currentRetryCount = 0; + final RxBool isFetchingDeviceInfo = true.obs; + + final RxDouble progress = 0.0.obs; // 控制器自己的可观察属性 + final RxInt type = OtaEvent.NOT_STARTED.obs; + final RxBool isUpgrade = false.obs; @override void onInit() { super.onInit(); @@ -62,6 +67,7 @@ class OtaUpgradeController extends GetxController { @override void onClose() { jlota.onOtaClose(); + isUpgrade.value = false; super.onClose(); } @@ -109,6 +115,7 @@ class OtaUpgradeController extends GetxController { } Future _getCurrentVersion() async { + _listenToEvents(); try { isFetchingDeviceInfo.value = true; errorMessage.value = ''; @@ -256,7 +263,7 @@ class OtaUpgradeController extends GetxController { headers: {'Accept-Encoding': 'gzip'}, )); - jlota.type.value = DOWNLOADING_UP_FILES; + type.value = DOWNLOADING_UP_FILES; try { final Directory? downloadsDir = await getDownloadsDirectory(); if (downloadsDir == null) { @@ -352,4 +359,45 @@ class OtaUpgradeController extends GetxController { return; // isUpgrade.value = false; } + + // 停止升级 + void stopUpgrading() async { + jlota.onOtaClose(); + return; + // isUpgrade.value = false; + } + + void _listenToEvents() { + Ota.instance.eventStream.listen((event) { + if (event.event == 'onProgress' && + event.type != null && + event.progress != null) { + progress.value = event.progress!; + type.value = event.type!; + isUpgrade.value = true; // 开始升级 + } + if (event.event == 'onStartOTA') { + type.value = OtaEvent.START_UPGRADING; + isUpgrade.value = true; // 开始升级 + } + if (event.event == 'onStopOTA') { + type.value = OtaEvent.UPGRADE_SUCCESS; + isUpgrade.value = false; + Get.snackbar('升级成功', '请退出重新连接设备'); + _getCurrentVersion(); + } + if (event.event == 'onError') { + type.value = OtaEvent.UPGRADE_FAILED; + isUpgrade.value = false; + } + if (event.event == 'NOCONNECTION') { + type.value = OtaEvent.CONNECTION_DISCONNECTION; + isUpgrade.value = false; + } + if (event.event == 'CONNECTION_SUCCESS') { + type.value = OtaEvent.CONNECTION_SUCCESS; + isUpgrade.value = true; // 开始升级 + } + }); + } } diff --git a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart index fe85296fc..1bb1629bc 100644 --- a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart +++ b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart @@ -10,70 +10,125 @@ class OtaUpgradeView extends GetView { Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; - return Scaffold( - backgroundColor: isDarkMode ? Colors.black : Colors.grey[100], - appBar: AppBar( - automaticallyImplyLeading: false, - centerTitle: true, - elevation: 0, - backgroundColor: isDarkMode ? Colors.black : Colors.white, - leading: IconButton( - icon: Icon( - Icons.arrow_back_ios, - size: 20.sp, - color: isDarkMode ? Colors.white : Colors.black, + return WillPopScope( + onWillPop: () async { + if (controller.isUpgrade.value) { + // 显示确认弹窗 + await Get.dialog( + AlertDialog( + title: Text('提示'), + content: Text('当前正在升级,退出将中断升级进程,确定要退出吗?'), + actions: [ + TextButton( + onPressed: () => Get.back(), // 关闭弹窗 + child: Text('取消'), + ), + TextButton( + onPressed: () { + controller.stopUpgrading(); + Get.back(); // 关闭弹窗 + Get.back(); // 返回上一页 + }, + child: Text('确定'), + ), + ], + ), + ); + return false; // 阻止默认返回 + } + return true; // 允许返回 + }, + child: Scaffold( + backgroundColor: isDarkMode ? Colors.black : Colors.grey[100], + appBar: AppBar( + automaticallyImplyLeading: false, + centerTitle: true, + elevation: 0, + backgroundColor: isDarkMode ? Colors.black : Colors.white, + leading: IconButton( + icon: Icon( + Icons.arrow_back_ios, + size: 20.sp, + color: isDarkMode ? Colors.white : Colors.black, + ), + onPressed: () { + if (controller.isUpgrade.value) { + // 显示确认弹窗 + Get.dialog( + AlertDialog( + title: Text('提示'), + content: Text('当前正在升级,退出将中断升级进程,确定要退出吗?'), + actions: [ + TextButton( + onPressed: () => Get.back(), // 关闭弹窗 + child: Text('取消'), + ), + TextButton( + onPressed: () { + controller.stopUpgrading(); + Get.back(); // 关闭弹窗 + Get.back(); // 返回上一页 + }, + child: Text('确定'), + ), + ], + ), + ); + } else { + Get.back(); // 正常返回 + } + }, ), - onPressed: () => Get.back(), - ), - title: Text( - '固件升级'.tr, - style: TextStyle( - fontSize: 20.sp, - color: isDarkMode ? Colors.white : Colors.black, + title: Text( + '固件升级'.tr, + style: TextStyle( + fontSize: 20.sp, + color: isDarkMode ? Colors.white : Colors.black, + ), ), ), - ), - body: SingleChildScrollView( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // 设备信息卡片 - Card( - elevation: 2, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - color: isDarkMode ? Colors.grey[900] : Colors.white, - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - children: [ - _buildDeviceIcon(isDarkMode), - SizedBox(height: 20), - _buildVersionInfo(isDarkMode), - ], + body: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // 设备信息卡片 + Card( + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + color: isDarkMode ? Colors.grey[900] : Colors.white, + child: Padding( + padding: EdgeInsets.all(20), + child: Column( + children: [ + _buildDeviceIcon(isDarkMode), + SizedBox(height: 20), + _buildVersionInfo(isDarkMode), + ], + ), ), ), - ), - SizedBox(height: 20), + SizedBox(height: 20), - // 更新说明 - _buildUpdateNotes(isDarkMode), - SizedBox(height: 20), + // 更新说明 + _buildUpdateNotes(isDarkMode), + SizedBox(height: 20), - // 状态显示区域 - Obx(() { - if (controller.isFetchingDeviceInfo.value) { - return _buildLoadingIndicator(isDarkMode); - } - if (controller.errorMessage.value.isNotEmpty) { - return _buildErrorInfo(isDarkMode); - } - return _buildUpdateButton(isDarkMode); - }), - ], + // 状态显示区域 + Obx(() { + if (controller.isFetchingDeviceInfo.value) { + return _buildLoadingIndicator(isDarkMode); + } + if (controller.errorMessage.value.isNotEmpty) { + return _buildErrorInfo(isDarkMode); + } + return _buildUpdateButton(isDarkMode); + }), + ], + ), ), ), ), @@ -227,7 +282,7 @@ class OtaUpgradeView extends GetView { ); Widget _buildUpdateButton(bool isDarkMode) { - return controller.jlota.isUpgrade.value + return controller.isUpgrade.value ? _buildProgressIndicator(isDarkMode) : Container( width: double.infinity, @@ -276,8 +331,8 @@ class OtaUpgradeView extends GetView { Widget _buildProgressIndicator(bool isDarkMode) { return Obx(() { - final progress = controller.jlota.progress.value; - final type = controller.jlota.type.value; + final progress = controller.progress.value; + final type = controller.type.value; // // 处理升级失败状态:弹出 snackbar 并显示错误提示 // if (type == OtaUpgradeController.UPGRADE_FAILED || diff --git a/local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index 8ed41b458..000000000 Binary files a/local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ diff --git a/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties b/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties deleted file mode 100644 index c231039ee..000000000 --- a/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Wed May 21 01:03:35 CST 2025 -gradle.version=8.9 diff --git a/local_plugins/ota/android/src/main/kotlin/com/example/ota/DeviceConnection.kt b/local_plugins/ota/android/src/main/kotlin/com/example/ota/DeviceConnection.kt deleted file mode 100644 index 0a9abdb19..000000000 --- a/local_plugins/ota/android/src/main/kotlin/com/example/ota/DeviceConnection.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.jieli.otasdk.model - -import android.bluetooth.BluetoothDevice - -/** - * @author zqjasonZhong - * @since 2022/9/9 - * @email zhongzhuocheng@zh-jieli.com - * @desc 设备连接状态 - */ -class DeviceConnection(val device: BluetoothDevice?, var state: Int) { - - override fun hashCode(): Int { - return device.hashCode() - } - - override fun equals(other: Any?): Boolean { - if (other !is DeviceConnection) return false - return device == other.device - } - - override fun toString(): String { - return "DeviceConnection(device=$device, state=$state)" - } - -} \ No newline at end of file diff --git a/local_plugins/ota/android/src/main/kotlin/com/example/ota/OtaPlugin.kt b/local_plugins/ota/android/src/main/kotlin/com/example/ota/OtaPlugin.kt index f082e3dad..c9d268c39 100644 --- a/local_plugins/ota/android/src/main/kotlin/com/example/ota/OtaPlugin.kt +++ b/local_plugins/ota/android/src/main/kotlin/com/example/ota/OtaPlugin.kt @@ -20,7 +20,6 @@ import com.jieli.jl_bt_ota.util.CHexConver import com.jieli.jl_bt_ota.util.JL_Log import com.jieli.otasdk.tool.bluetooth.BluetoothHelper import androidx.lifecycle.MutableLiveData -import com.jieli.otasdk.model.DeviceConnection import android.util.Log import androidx.annotation.NonNull import com.jieli.otasdk.tool.config.ConfigHelper @@ -309,7 +308,11 @@ class OtaPlugin : BleService.Callback, FlutterPlugin, MethodCallHandler { otaDevice = bluetoothGatt.device BleService.disconnect() - } else { + } else if(otaDevice != null) + { isDisconnect = true + BleService.disconnect() + } + else{ Log.e("TAG", "BluetoothGatt 或 device 为 null,无法执行操作") sendEventOnMainThread( mapOf( @@ -324,6 +327,8 @@ class OtaPlugin : BleService.Callback, FlutterPlugin, MethodCallHandler { } else if (call.method == "onOtaClose") { BleService.isEnterOta = false isDisconnect = false + otaManager.bluetoothHelper.stopScan() + otaManager.bluetoothHelper.disconnectDevice(otaDevice) } else { result.notImplemented() } diff --git a/local_plugins/ota/android/src/main/kotlin/com/example/ota/tool/ota/ble/BleManager.java b/local_plugins/ota/android/src/main/kotlin/com/example/ota/tool/ota/ble/BleManager.java index 04f53d8e9..aa5708974 100644 --- a/local_plugins/ota/android/src/main/kotlin/com/example/ota/tool/ota/ble/BleManager.java +++ b/local_plugins/ota/android/src/main/kotlin/com/example/ota/tool/ota/ble/BleManager.java @@ -646,9 +646,10 @@ public class BleManager { } else { Log.e(TAG, "连接设备失败: ${device.name} (${device.address})"); } - } + mDiscoveredBleDevices.add(device); handleDiscoveryBle(device, new BleScanInfo().setRawData(scanRecord).setRssi(rssi).setEnableConnect(isBleEnableConnect)); + } } } diff --git a/local_plugins/ota/lib/ota.dart b/local_plugins/ota/lib/ota.dart index 871fa4198..e21eb0a8d 100644 --- a/local_plugins/ota/lib/ota.dart +++ b/local_plugins/ota/lib/ota.dart @@ -2,7 +2,6 @@ import 'ota_platform_interface.dart'; import 'dart:async'; import 'dart:typed_data'; import 'package:flutter/services.dart'; -import 'package:get/get.dart'; class OtaEvent { static final int NOT_STARTED = -1; // 未开始 @@ -57,7 +56,7 @@ class Ota { // 私有构造函数 Ota._internal() { // 初始化时设置事件监听 - _setupEventListener(); + // _setupEventListener(); } // 公共访问点 @@ -66,13 +65,13 @@ class Ota { static const EventChannel _eventChannel = EventChannel( 'com.example.ota/events', ); - final RxDouble progress = 0.0.obs; - final RxInt type = OtaEvent.NOT_STARTED.obs; - final RxBool isUpgrade = false.obs; + // double progress = 0.0; + // late int type = OtaEvent.NOT_STARTED; + // bool isUpgrade = false; /// 事件流 Stream? _eventStream; - bool _isEventListenerSet = false; // 防止重复监听 + // bool _isEventListenerSet = false; // 防止重复监听 /// 获取事件流 Stream get eventStream { @@ -90,53 +89,48 @@ class Ota { onOtaClose(); // 停止事件监听 _eventStream = null; - _isEventListenerSet = false; - - // 清理 Rx 对象 - progress.close(); - type.close(); - isUpgrade.value = false; + //_isEventListenerSet = false; print("Ota 对象资源已释放"); } - /// 内部设置事件监听(只执行一次) - void _setupEventListener() { - if (_isEventListenerSet) return; - - eventStream.listen((event) { - if (event.event == 'onProgress' && - event.type != null && - event.progress != null) { - print("flutter 收到数据${event.progress}type=${type.value}"); - progress.value = event.progress!; - type.value = event.type!; - } - if (event.event == 'onStartOTA') { - type.value = OtaEvent.START_UPGRADING; - isUpgrade.value = true; // 开始升级 - } - if (event.event == 'onStopOTA') { - type.value = OtaEvent.UPGRADE_SUCCESS; - isUpgrade.value = false; - } - if (event.event == 'onError' && - event.code != null && - event.message != null) { - print("flutter onError${event.code}type=${event.message}"); - type.value = OtaEvent.UPGRADE_FAILED; - isUpgrade.value = false; - } - if (event.event == 'NOCONNECTION') { - type.value = OtaEvent.CONNECTION_DISCONNECTION; - isUpgrade.value = false; - } - if (event.event == 'CONNECTION_SUCCESS') { - type.value = OtaEvent.CONNECTION_SUCCESS; - } - }); - - _isEventListenerSet = true; - } + // /// 内部设置事件监听(只执行一次) + // void _setupEventListener() { + // if (_isEventListenerSet) return; + + // eventStream.listen((event) { + // if (event.event == 'onProgress' && + // event.type != null && + // event.progress != null) { + // print("flutter 收到数据${event.progress}type=${type}"); + // progress = event.progress!; + // type = event.type!; + // } + // if (event.event == 'onStartOTA') { + // type = OtaEvent.START_UPGRADING; + // isUpgrade = true; // 开始升级 + // } + // if (event.event == 'onStopOTA') { + // type = OtaEvent.UPGRADE_SUCCESS; + // isUpgrade = false; + // } + // if (event.event == 'onError' && + // event.code != null && + // event.message != null) { + // print("flutter onError${event.code}type=${event.message}"); + // type = OtaEvent.UPGRADE_FAILED; + // isUpgrade = false; + // } + // if (event.event == 'NOCONNECTION') { + // type = OtaEvent.CONNECTION_DISCONNECTION; + // isUpgrade = false; + // } + // if (event.event == 'CONNECTION_SUCCESS') { + // type = OtaEvent.CONNECTION_SUCCESS; + // } + // }); + + // _isEventListenerSet = true; + // } Future startUpgrading(String? filePath) { return OtaPlatform.instance.startUpgrading(filePath); diff --git a/local_plugins/ota/pubspec.yaml b/local_plugins/ota/pubspec.yaml index 6361a0944..7db9dc8a6 100644 --- a/local_plugins/ota/pubspec.yaml +++ b/local_plugins/ota/pubspec.yaml @@ -11,7 +11,6 @@ dependencies: flutter: sdk: flutter plugin_platform_interface: ^2.0.2 - get: ^4.6.5 dev_dependencies: flutter_test: sdk: flutter