diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index fc2da7300..89bcfdef7 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -5,6 +5,7 @@ repositories { mavenCentral() flatDir { dirs(project(":spotify_sdk").projectDir.resolve("libs")) + dirs(project(":jl_ota").projectDir.resolve("libs")) } } diff --git a/lib/core/translations/language/zh_cn.dart b/lib/core/translations/language/zh_cn.dart index 24d8d3c95..5a7b3b7d5 100644 --- a/lib/core/translations/language/zh_cn.dart +++ b/lib/core/translations/language/zh_cn.dart @@ -123,6 +123,7 @@ const Map zhCN = { "allRoundAssistant": "全能助理", "allRoundAssistantInfo": "帮你解决各类问题", "simultaneousTranslation": "同声翻译", + "faceToFaceTranslation": "面对面翻译", 'audioVideoTranslation': '音视频翻译', 'callTranslation': '通话翻译', "simultaneousTranslationInfo": "实时翻译80+种语言", diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart index 0f826a7c4..8ce3b77b6 100644 --- a/lib/data/services/ble_manager.dart +++ b/lib/data/services/ble_manager.dart @@ -54,7 +54,7 @@ class DeviceInfo { this.rightEarCharging = false, this.caseCharging = false, this.firmwareVersion = '', - this.firmwareProductId = '', + this.firmwareProductId = 's3', this.firmwareProductColor = '', DateTime? lastUpdated, }) : lastUpdated = lastUpdated ?? DateTime.now(); diff --git a/lib/modules/login/controllers/login_controller.dart b/lib/modules/login/controllers/login_controller.dart index fa2baa534..4eb9c327c 100644 --- a/lib/modules/login/controllers/login_controller.dart +++ b/lib/modules/login/controllers/login_controller.dart @@ -695,8 +695,8 @@ class LoginController extends GetxController { await _storage.write("logintoken", response['token'].toString()); // 存储到 SharedPreferences (仅存储用户数据) //final prefs = await GetStorage(); - await _storage.write( - 'user', jsonEncode(user.toJson())); // 使用 user.toJson() + await _storage.write('user_info', user.toJson()); + //获取app的配置信息 await getAppConfig(); Get.offAllNamed(Routes.pairing); diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 1e59b45c3..4aa7f04f6 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -7,6 +7,7 @@ import '../model/ota_upgrade_model.dart'; import 'dart:io'; import 'package:dio/dio.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:jl_ota/jl_ota.dart'; import '../../../data/services/ble_manager.dart'; class OtaUpgradeController extends GetxController { @@ -40,6 +41,8 @@ class OtaUpgradeController extends GetxController { Future startUpdate() async { try { isUpdating.value = true; + checkUpdate(); + // 实现更新逻辑... } catch (e) { errorMessage.value = e.toString(); @@ -50,64 +53,68 @@ class OtaUpgradeController extends GetxController { } Future _getCurrentVersion() async { - try { - // 添加获取设备信息的重试机制 - DeviceInfo? deviceInfo = _bleManager.deviceInfo.value; - - // 第一次检查设备信息 - if (deviceInfo == null) { - // 显示加载提示 - isFetchingDeviceInfo.value = true; - - // 尝试重新获取设备信息 - await _bleManager.fetchDeviceInfo(); - - // 等待后再次获取设备信息 - deviceInfo = _bleManager.deviceInfo.value; - isFetchingDeviceInfo.value = false; - - // 仍然为空则抛出异常 - if (deviceInfo == null) { - throw const FormatException('无法获取设备信息,请检查设备连接'); - } - } - - // 检查固件信息有效性 - if (deviceInfo.firmwareVersion.isEmpty || - deviceInfo.firmwareProductId.isEmpty) { - throw const FormatException('设备固件信息不完整'); - } - - // 正常流程 - currentVersion.value = deviceInfo.firmwareVersion; - - // API请求 - final response = await Api.getequipmentinfo({ - "id": deviceInfo.firmwareProductId, - }); - - // 处理API响应 - if (response['info'] == null) { - throw const FormatException('API 响应格式错误'); - } - - final resp = OtaConfigResp.fromJson(response); - latestVersion.value = resp.systemversion!; - updatepackageaddress = resp.updatepackageaddress!; - - // 版本检查 - isUpdateAvailable.value = _isNewVersionAvailable(resp.systemversion!); - } catch (e) { - // 统一错误处理 - errorMessage.value = e.toString(); - Get.snackbar('错误', e.toString(), - snackPosition: SnackPosition.BOTTOM, - backgroundColor: Colors.red, - colorText: Colors.white); - // 重要:重新抛出异常以便上层处理(可选) - } finally { - isFetchingDeviceInfo.value = false; - } + JlOta().getPlatformVersion(); + //try { + + // // 添加获取设备信息的重试机制 + // DeviceInfo? deviceInfo = _bleManager.deviceInfo.value; + + // // 第一次检查设备信息 + // if (deviceInfo == null) { + // // 显示加载提示 + // isFetchingDeviceInfo.value = true; + + // // 尝试重新获取设备信息 + // await _bleManager.fetchDeviceInfo(); + + // // 等待后再次获取设备信息 + // deviceInfo = _bleManager.deviceInfo.value; + // isFetchingDeviceInfo.value = false; + + // // 仍然为空则抛出异常 + // if (deviceInfo == null) { + // throw const FormatException('无法获取设备信息,请检查设备连接'); + // } + // } + + // // 检查固件信息有效性 + // if (deviceInfo.firmwareVersion.isEmpty + // // || + // // deviceInfo.firmwareProductId.isEmpty + // ) { + // throw const FormatException('设备固件信息不完整'); + // } + + // // 正常流程 + // currentVersion.value = "0"; //deviceInfo.firmwareVersion; + + // // API请求 + // final response = await Api.getequipmentinfo({ + // "id": "s3", + // }); + + // // 处理API响应 + // if (response['info'] == null) { + // throw const FormatException('API 响应格式错误'); + // } + + // final resp = OtaConfigResp.fromJson(response); + // latestVersion.value = resp.systemversion!; + // updatepackageaddress = resp.updatepackageaddress!; + + // // 版本检查 + // isUpdateAvailable.value = _isNewVersionAvailable(resp.systemversion!); + // } catch (e) { + // // 统一错误处理 + // errorMessage.value = e.toString(); + // Get.snackbar('错误', e.toString(), + // snackPosition: SnackPosition.BOTTOM, + // backgroundColor: Colors.red, + // colorText: Colors.white); + // // 重要:重新抛出异常以便上层处理(可选) + // } finally { + // isFetchingDeviceInfo.value = false; + // } } // 版本比较方法优化 @@ -288,6 +295,7 @@ class OtaUpgradeController extends GetxController { // 开始升级 void _installApp(String path) async { + // JlOtaPlugin() // final File file = File(path); // if (await file.exists()) { // // OpenResult result = await OpenFile.open(path); diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index 7962d629f..1b2c8afd3 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -59,6 +59,9 @@ class TranslationController extends GetxController { return 'audioVideoTranslation'; case 'call': return 'callTranslation'; + case 'faceToFace': + return 'faceToFaceTranslation'; + default: return 'simultaneousTranslation'; } diff --git a/lib/modules/translation/views/translation_view.dart b/lib/modules/translation/views/translation_view.dart index 5908b0691..257e32a63 100644 --- a/lib/modules/translation/views/translation_view.dart +++ b/lib/modules/translation/views/translation_view.dart @@ -57,6 +57,7 @@ class TranslationView extends GetView { color: isDarkMode ? AppColors.cardBackground : Colors.white, itemBuilder: (BuildContext context) => [ _buildPopupMenuItem('simultaneous', 'simultaneousTranslation'.tr), + _buildPopupMenuItem('faceToFace', 'faceToFaceTranslation'.tr), _buildPopupMenuItem('audioVideo', 'audioVideoTranslation'.tr), _buildPopupMenuItem('call', 'callTranslation'.tr), ], @@ -86,12 +87,11 @@ class TranslationView extends GetView { // TTS toggle button Obx(() => IconButton( icon: Icon( - controller.isTtsEnabled.value - ? Icons.volume_up - : Icons.volume_off, + controller.isTtsEnabled.value ? Icons.mic : Icons.mic_off, color: isDarkMode ? Colors.white : Colors.black, size: 24.sp, ), + // onPressed: controller.toggleTts,默认播放 onPressed: controller.toggleTts, tooltip: '自动播放翻译结果', )), diff --git a/local_plugins/jieli/android/build.gradle.kts b/local_plugins/jieli/android/build.gradle.kts index e804da665..a8a6e7ac4 100644 --- a/local_plugins/jieli/android/build.gradle.kts +++ b/local_plugins/jieli/android/build.gradle.kts @@ -54,5 +54,4 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2") implementation(project(":azure_speech")) implementation(project(":jl_opus")) - implementation(project(":jl_opus")) } \ No newline at end of file diff --git a/local_plugins/jl_ota/.gitignore b/local_plugins/jl_ota/.gitignore new file mode 100644 index 000000000..e7d347d9d --- /dev/null +++ b/local_plugins/jl_ota/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +build/ diff --git a/local_plugins/jl_ota/.metadata b/local_plugins/jl_ota/.metadata new file mode 100644 index 000000000..6015b831a --- /dev/null +++ b/local_plugins/jl_ota/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "ea121f8859e4b13e47a8f845e4586164519588bc" + channel: "stable" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: android + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: ios + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/local_plugins/jl_ota/CHANGELOG.md b/local_plugins/jl_ota/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/local_plugins/jl_ota/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/local_plugins/jl_ota/LICENSE b/local_plugins/jl_ota/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/local_plugins/jl_ota/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/local_plugins/jl_ota/README.md b/local_plugins/jl_ota/README.md new file mode 100644 index 000000000..673c7a29a --- /dev/null +++ b/local_plugins/jl_ota/README.md @@ -0,0 +1,15 @@ +# jl_ota + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/to/develop-plugins), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/local_plugins/jl_ota/analysis_options.yaml b/local_plugins/jl_ota/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/local_plugins/jl_ota/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/local_plugins/jl_ota/android/.gitignore b/local_plugins/jl_ota/android/.gitignore new file mode 100644 index 000000000..161bdcdaf --- /dev/null +++ b/local_plugins/jl_ota/android/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/local_plugins/jl_ota/android/build.gradle b/local_plugins/jl_ota/android/build.gradle new file mode 100644 index 000000000..76e296450 --- /dev/null +++ b/local_plugins/jl_ota/android/build.gradle @@ -0,0 +1,71 @@ +group = "com.yunqiinnovation.jl_ota" +version = "1.0-SNAPSHOT" + +buildscript { + ext.kotlin_version = "1.8.22" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:8.7.0") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } +} + +allprojects { + repositories { + google() + mavenCentral() + flatDir { + dirs 'libs' + } + } +} + +apply plugin: "com.android.library" +apply plugin: "kotlin-android" + +android { + namespace = "com.yunqiinnovation.jl_ota" + + compileSdk = 35 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11 + } + + sourceSets { + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" + } + + defaultConfig { + minSdk = 21 + } + + dependencies { + implementation(name: 'jl_bt_ota_V1.9.0-release', ext: 'aar') + implementation(project(":ble_service")) + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.mockito:mockito-core:5.0.0") + } + + testOptions { + unitTests.all { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true + } + } + } +} diff --git a/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.0-release.aar b/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.0-release.aar new file mode 100644 index 000000000..c33c59d48 Binary files /dev/null and b/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.0-release.aar differ diff --git a/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.2-release.aar b/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.2-release.aar new file mode 100644 index 000000000..9ecf85489 Binary files /dev/null and b/local_plugins/jl_ota/android/libs/jl_bt_ota_V1.9.2-release.aar differ diff --git a/local_plugins/jl_ota/android/settings.gradle b/local_plugins/jl_ota/android/settings.gradle new file mode 100644 index 000000000..d5825d78e --- /dev/null +++ b/local_plugins/jl_ota/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'jl_ota' diff --git a/local_plugins/jl_ota/android/src/main/AndroidManifest.xml b/local_plugins/jl_ota/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..efb57f32c --- /dev/null +++ b/local_plugins/jl_ota/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/local_plugins/jl_ota/android/src/main/kotlin/com/yunqiinnovation/jl_ota/JlOtaPlugin.kt b/local_plugins/jl_ota/android/src/main/kotlin/com/yunqiinnovation/jl_ota/JlOtaPlugin.kt new file mode 100644 index 000000000..c61dfc70d --- /dev/null +++ b/local_plugins/jl_ota/android/src/main/kotlin/com/yunqiinnovation/jl_ota/JlOtaPlugin.kt @@ -0,0 +1,279 @@ +package com.yunqiinnovation.jl_ota + +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothDevice +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log +import androidx.annotation.NonNull + +import com.jieli.jl_bt_ota.constant.ErrorCode; +import com.jieli.jl_bt_ota.constant.StateCode; +import com.jieli.jl_bt_ota.impl.BluetoothOTAManager; +import com.jieli.jl_bt_ota.interfaces.BtEventCallback; +import com.jieli.jl_bt_ota.interfaces.IActionCallback; +import com.jieli.jl_bt_ota.interfaces.IUpgradeCallback; +import com.jieli.jl_bt_ota.model.BluetoothOTAConfigure; +import com.jieli.jl_bt_ota.model.base.BaseError; +import com.jieli.jl_bt_ota.model.response.TargetInfoResponse; + + +import com.yunqiinnovation.ble_service.BleService +/** JlOtaPlugin */ +class JlOtaPlugin(): FlutterPlugin, MethodCallHandler { + /// The MethodChannel that will the communication between Flutter and native Android + /// + /// This local reference serves to register the plugin with the Flutter Engine and unregister it + /// when the Flutter Engine is detached from the Activity + private lateinit var channel : MethodChannel + private lateinit var context: Context + private lateinit var eventChannel: EventChannel + private var streamSink: EventChannel.EventSink? = null + /// BLE服务实例 + private var otaManager: OTAManager? = null + + + companion object { + private const val TAG = "JlOtaPlugin" + private const val CHANNEL_NAME = "com.yunqiinnovation.jl_ota" + private const val EVENT_CHANNEL_NAME = "com.yunqiinnovation.jl_ota/events" + + } + + override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + context = flutterPluginBinding.applicationContext + channel = MethodChannel(flutterPluginBinding.binaryMessenger, "jl_ota") + channel.setMethodCallHandler(this) + + eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, EVENT_CHANNEL_NAME) + + eventChannel.setStreamHandler(object : EventChannel.StreamHandler { + override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { + streamSink = events + } + + override fun onCancel(arguments: Any?) { + streamSink = null + } + }) + + + otaManager = OTAManager(context) + +// otaManager.getBluetoothOption().setFirmwareFilePath(filePath); +// otaManager.startOTA(new IUpgradeCallback() { +// } + + } + + override fun onMethodCall(call: MethodCall, result: Result) { + if (call.method == "getPlatformVersion") { + + val bluetoothOption = BluetoothOTAConfigure() + //选择通讯方式 + bluetoothOption.priority = BluetoothOTAConfigure.PREFER_BLE + //是否需要自定义回连方式(默认不需要,如需要自定义回连方式,需要客户自行实现) + bluetoothOption.isUseReconnect = true + //是否启用设备认证流程(与固件工程师确认) + bluetoothOption.isUseAuthDevice = true + //设置BLE的MTU + bluetoothOption.mtu = 500 + //是否需要改变BLE的MTU + bluetoothOption.isNeedChangeMtu = false + //是否启用杰理服务器(暂时不支持) + bluetoothOption.isUseJLServer = false + Log.d(TAG, "bluetoothOTAManager初始化成功") + //配置OTA参数 + otaManager?.configure(bluetoothOption) + + + var filePath= "/storage/emulated/0/Android/data/com.yunqiinnovation.deepsound/files/downloads/ota_upgrades/1.ufw" +otaManager?.bluetoothOption?.firmwareFilePath = filePath +Log.d(TAG, "OpusManager路径成功${filePath}") +// Add ?. after bluetoothOption ^ + otaManager?.startOTA( + CustomUpdateCallback( + context, null, this + ) + ) + result.success("Android ${android.os.Build.VERSION.RELEASE}") + } else { + result.notImplemented() + } + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } + +} +class OTAManager(context: Context) : BluetoothOTAManager(context) { + override fun getConnectedDevice(): BluetoothDevice? { + // 这里可以添加空实现的注释说明 + return null +} + override fun getConnectedBluetoothGatt(): BluetoothGatt? { + // 这里可以添加空实现的注释说明 + return null +} + override fun connectBluetoothDevice(bluetoothDevice: BluetoothDevice?) { + // 这里可以添加空实现的注释说明 + +} +override fun disconnectBluetoothDevice +(bluetoothDevice: BluetoothDevice?) { + // 这里可以添加空实现的注释说明 + +} + /** 数据发送方法(协议无关) */ + override fun sendDataToDevice( + bluetoothDevice: BluetoothDevice?, + bytes: ByteArray? + ): Boolean {return true} +} + +private class CustomUpdateCallback( + val context: Context, + val device: BluetoothDevice?, + val viewModel: JlOtaPlugin + ) : IUpgradeCallback{ + companion object { + private const val TAG = "JlOtaPlugin" + private const val CHANNEL_NAME = "com.yunqiinnovation.jl_ota" + private const val EVENT_CHANNEL_NAME = "com.yunqiinnovation.jl_ota/events" + + } + override fun onStartOTA() { + Log.d(TAG, "onStartOTA开始升级") + // viewModel.otaStateMLD.value = OTAStart(device) + } + + override fun onNeedReconnect(addr: String?, isNewReconnectWay: Boolean) { + Log.d(TAG, "onNeedReconnect需要重新链接") + // viewModel.otaStateMLD.value = OTAReconnect(device, addr, isNewReconnectWay) + // if (viewModel.isUseReconnectWay()) { + // viewModel.reconnectDev(addr, isNewReconnectWay) + // } + } + + override fun onProgress(type: Int, progress: Float) { + Log.d(TAG, "onProgress正在进展") + //viewModel.otaStateMLD.value = OTAWorking(device, type, progress) + } + + override fun onStopOTA() { + Log.d(TAG, "onStartOTA停止升级") +// viewModel.otaStateMLD.value = +// OTAEnd(device, ErrorCode.ERR_NONE, context.getString(R.string.ota_complete)) +// val handler = Handler(Looper.getMainLooper()) +// handler.postDelayed({ +// // Log.d("ZHM", "onStopOTA: disconnectDevice connected : "+viewModel.bluetoothHelper.isConnected()+ " getConnectedDevice: "+viewModel.bluetoothHelper.getConnectedDevice()) +// //变地址导致无法判断device是否一致 +// if (viewModel.bluetoothHelper.isConnected()/* && BluetoothUtil.deviceEquals( +// device, +// viewModel.bluetoothHelper.getConnectedDevice() +// )*/ +// ) { +// Log.d("ZHM", "onStopOTA: disconnectDevice") +// viewModel.bluetoothHelper.disconnectDevice(viewModel.otaManager.connectedDevice) +// } +// }, 500) + } + + override fun onCancelOTA() { + Log.d(TAG, "onCancelOTA取消升级") + // viewModel.otaStateMLD.value = + // OTAEnd( + // device, + // ErrorCode.ERR_UNKNOWN, + // context.getString(R.string.ota_upgrade_cancel) + // ) + } + + override fun onError(error: BaseError?) { + Log.d(TAG, "onError升级错误") + // error?.let { + // viewModel.otaStateMLD.value = OTAEnd(device, it.subCode, it.message) + // } + // viewModel.bluetoothHelper.disconnectDevice(viewModel.otaManager.connectedDevice)//升级失败,断开设备,方便自动化继续升级 + } + } +// class OtaDemo { +// private val otaManager = OTAManager(MainApplication.getInstance()) + // fun initOTA(context: Context, firmwarePath: String) { + // val otaManager = JlOtaPlugin() + // val bluetoothOption = BluetoothOTAConfigure.createDefault().apply { + // priority = BluetoothOTAConfigure.PREFER_BLE + // useAuthDevice = true + // bleIntervalMs = 500 + // timeoutMs = 3000 + // mtu = 500 + // needChangeMtu = false + // useReconnect = false + // setFirmwareFilePath(firmwarePath) + // } + // otaManager.configure(bluetoothOption) + // } + + // fun otaFirmware(filePath: String) { // 方法名改为小写开头 + // val otaManager = JlOtaPlugin() + + // otaManager.registerBluetoothCallback(object : BtEventCallback { + // override fun onConnection(device: BluetoothDevice, status: Int) { + // if (status == StateCode.CONNECTION_OK) { + // if (otaManager.isOTA) return + + // otaManager.queryMandatoryUpdate(object : IActionCallback { + // override fun onSuccess(deviceInfo: TargetInfoResponse) { + // // 处理设备信息 + // deviceInfo.versionCode + // deviceInfo.versionName + // deviceInfo.projectCode + // deviceInfo.uid + // deviceInfo.pid + // } + + // override fun onError(baseError: BaseError) { + // if (baseError.code == ErrorCode.ERR_NONE && + // baseError.subCode == ErrorCode.ERR_NONE) { + // val deviceInfo = otaManager.deviceInfo + // deviceInfo?.let { + // it.versionCode + // it.versionName + // it.projectCode + // it.uid + // it.pid + // } + // } + // } + // }) + // } + // } + // }) + + // otaManager.bluetoothOption?.setFirmwareFilePath(filePath) + + // otaManager.startOTA(object : IUpgradeCallback { + // override fun onStartOTA() = Unit + // override fun onNeedReconnect(addr: String, isNewReconnectWay: Boolean) { + // if (otaManager.bluetoothOption?.useReconnect == true) { + // // 处理自定义回连 + // } + // } + // override fun onProgress(type: Int, progress: Float) = Unit + // override fun onStopOTA() = Unit + // override fun onCancelOTA() = Unit + // override fun onError(error: BaseError) = Unit + // }) + + // otaManager.release() + // } +//} \ No newline at end of file diff --git a/local_plugins/jl_ota/ios/.gitignore b/local_plugins/jl_ota/ios/.gitignore new file mode 100644 index 000000000..034771fc9 --- /dev/null +++ b/local_plugins/jl_ota/ios/.gitignore @@ -0,0 +1,38 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/ephemeral/ +/Flutter/flutter_export_environment.sh diff --git a/local_plugins/jl_ota/ios/Assets/.gitkeep b/local_plugins/jl_ota/ios/Assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/local_plugins/jl_ota/ios/Classes/JlOtaPlugin.swift b/local_plugins/jl_ota/ios/Classes/JlOtaPlugin.swift new file mode 100644 index 000000000..e5b6434f2 --- /dev/null +++ b/local_plugins/jl_ota/ios/Classes/JlOtaPlugin.swift @@ -0,0 +1,19 @@ +import Flutter +import UIKit + +public class JlOtaPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "jl_ota", binaryMessenger: registrar.messenger()) + let instance = JlOtaPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformVersion": + result("iOS " + UIDevice.current.systemVersion) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/local_plugins/jl_ota/ios/Resources/PrivacyInfo.xcprivacy b/local_plugins/jl_ota/ios/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..a34b7e2e6 --- /dev/null +++ b/local_plugins/jl_ota/ios/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/local_plugins/jl_ota/ios/jl_ota.podspec b/local_plugins/jl_ota/ios/jl_ota.podspec new file mode 100644 index 000000000..ebd8d61ed --- /dev/null +++ b/local_plugins/jl_ota/ios/jl_ota.podspec @@ -0,0 +1,29 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint jl_ota.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'jl_ota' + s.version = '0.0.1' + s.summary = 'A new Flutter project.' + s.description = <<-DESC +A new Flutter project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '12.0' + + # Flutter.framework does not contain a i386 slice. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.swift_version = '5.0' + + # If your plugin requires a privacy manifest, for example if it uses any + # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your + # plugin's privacy impact, and then uncomment this line. For more information, + # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files + # s.resource_bundles = {'jl_ota_privacy' => ['Resources/PrivacyInfo.xcprivacy']} +end diff --git a/local_plugins/jl_ota/lib/jl_ota.dart b/local_plugins/jl_ota/lib/jl_ota.dart new file mode 100644 index 000000000..ed1f427bd --- /dev/null +++ b/local_plugins/jl_ota/lib/jl_ota.dart @@ -0,0 +1,8 @@ + +import 'jl_ota_platform_interface.dart'; + +class JlOta { + Future getPlatformVersion() { + return JlOtaPlatform.instance.getPlatformVersion(); + } +} diff --git a/local_plugins/jl_ota/lib/jl_ota_method_channel.dart b/local_plugins/jl_ota/lib/jl_ota_method_channel.dart new file mode 100644 index 000000000..aa4647443 --- /dev/null +++ b/local_plugins/jl_ota/lib/jl_ota_method_channel.dart @@ -0,0 +1,17 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'jl_ota_platform_interface.dart'; + +/// An implementation of [JlOtaPlatform] that uses method channels. +class MethodChannelJlOta extends JlOtaPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('jl_ota'); + + @override + Future getPlatformVersion() async { + final version = await methodChannel.invokeMethod('getPlatformVersion'); + return version; + } +} diff --git a/local_plugins/jl_ota/lib/jl_ota_platform_interface.dart b/local_plugins/jl_ota/lib/jl_ota_platform_interface.dart new file mode 100644 index 000000000..f4c504da7 --- /dev/null +++ b/local_plugins/jl_ota/lib/jl_ota_platform_interface.dart @@ -0,0 +1,29 @@ +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'jl_ota_method_channel.dart'; + +abstract class JlOtaPlatform extends PlatformInterface { + /// Constructs a JlOtaPlatform. + JlOtaPlatform() : super(token: _token); + + static final Object _token = Object(); + + static JlOtaPlatform _instance = MethodChannelJlOta(); + + /// The default instance of [JlOtaPlatform] to use. + /// + /// Defaults to [MethodChannelJlOta]. + static JlOtaPlatform get instance => _instance; + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [JlOtaPlatform] when + /// they register themselves. + static set instance(JlOtaPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future getPlatformVersion() { + throw UnimplementedError('platformVersion() has not been implemented.'); + } +} diff --git a/local_plugins/jl_ota/pubspec.yaml b/local_plugins/jl_ota/pubspec.yaml new file mode 100644 index 000000000..d54089c80 --- /dev/null +++ b/local_plugins/jl_ota/pubspec.yaml @@ -0,0 +1,72 @@ +name: jl_ota +description: "A new Flutter project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.7.2 + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + android: + package: com.yunqiinnovation.jl_ota + pluginClass: JlOtaPlugin + ios: + pluginClass: JlOtaPlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/pubspec.yaml b/pubspec.yaml index 608ba936e..2d0ff76aa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,6 +79,8 @@ dependencies: path: amap_flutter jl_opus: path: local_plugins/jl_opus + jl_ota: + path: local_plugins/jl_ota ble_service: path: local_plugins/ble_service deepvoice_utils: