Browse Source

优化ota升级

weicu
fdp 1 year ago
parent
commit
756c1001be
  1. 13
      lib/data/services/ble_manager.dart
  2. 52
      lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart
  3. 175
      lib/modules/ota_upgrade/views/ota_upgrade_view.dart
  4. BIN
      local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock
  5. 2
      local_plugins/opus/.gradle/buildOutputCleanup/cache.properties
  6. 26
      local_plugins/ota/android/src/main/kotlin/com/example/ota/DeviceConnection.kt
  7. 9
      local_plugins/ota/android/src/main/kotlin/com/example/ota/OtaPlugin.kt
  8. 3
      local_plugins/ota/android/src/main/kotlin/com/example/ota/tool/ota/ble/BleManager.java
  9. 94
      local_plugins/ota/lib/ota.dart
  10. 1
      local_plugins/ota/pubspec.yaml

13
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: '',
);
}
}

52
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<BleManager>();
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<void> _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; // 开始升级
}
});
}
}

175
lib/modules/ota_upgrade/views/ota_upgrade_view.dart

@ -10,70 +10,125 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
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<OtaUpgradeController> {
);
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<OtaUpgradeController> {
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 ||

BIN
local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock

Binary file not shown.

2
local_plugins/opus/.gradle/buildOutputCleanup/cache.properties

@ -1,2 +0,0 @@
#Wed May 21 01:03:35 CST 2025
gradle.version=8.9

26
local_plugins/ota/android/src/main/kotlin/com/example/ota/DeviceConnection.kt

@ -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)"
}
}

9
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()
}

3
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));
}
}
}

94
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<OtaEvent>? _eventStream;
bool _isEventListenerSet = false; // 防止重复监听
// bool _isEventListenerSet = false; // 防止重复监听
/// 获取事件流
Stream<OtaEvent> 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<String?> startUpgrading(String? filePath) {
return OtaPlatform.instance.startUpgrading(filePath);

1
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

Loading…
Cancel
Save