diff --git a/assets/file.json b/assets/file.json index 0459698..c64c693 100644 --- a/assets/file.json +++ b/assets/file.json @@ -1,3 +1,3 @@ [ - "assets/miniapp/mhtControl_1.0.69.zip" + "assets/miniapp/mhtControl_1.0.74.zip" ] \ No newline at end of file diff --git a/assets/miniapp/mhtControl_1.0.69.zip b/assets/miniapp/mhtControl_1.0.74.zip similarity index 97% rename from assets/miniapp/mhtControl_1.0.69.zip rename to assets/miniapp/mhtControl_1.0.74.zip index 9442d2e..81bad01 100644 Binary files a/assets/miniapp/mhtControl_1.0.69.zip and b/assets/miniapp/mhtControl_1.0.74.zip differ diff --git a/lib/common/util/BluetoothHelper.dart b/lib/common/util/BluetoothHelper.dart new file mode 100644 index 0000000..1714a6d --- /dev/null +++ b/lib/common/util/BluetoothHelper.dart @@ -0,0 +1,39 @@ +import 'dart:async'; +import 'package:flutter_blue_plus/flutter_blue_plus.dart'; + +class BluetoothHelper { + static StreamSubscription? _subscription; + + /// 获取当前蓝牙是否开启(跨平台封装) + static Future isBluetoothOn({Duration timeout = const Duration(seconds: 2)}) async { + // 先尝试直接获取(Android 上几乎即时可用) + bool directCheck = await FlutterBluePlus.isOn; + if (directCheck) return true; + + // iOS 上有初始化延迟,用 adapterState.first 再确认一次 + try { + BluetoothAdapterState state = await FlutterBluePlus.adapterState + .firstWhere((s) => s != BluetoothAdapterState.unknown, + orElse: () => BluetoothAdapterState.unknown) + .timeout(timeout); + + return state == BluetoothAdapterState.on; + } catch (_) { + return false; + } + } + + /// 监听蓝牙状态变化 + static void listenBluetoothState(void Function(bool isOn) onChange) { + _subscription?.cancel(); + _subscription = FlutterBluePlus.adapterState.listen((state) { + onChange(state == BluetoothAdapterState.on); + }); + } + + /// 停止监听 + static void cancelListener() { + _subscription?.cancel(); + _subscription = null; + } +} diff --git a/lib/pages/mh_page/device/mht_blueteeth_device_page.dart b/lib/pages/mh_page/device/mht_blueteeth_device_page.dart index c6903b7..119d82e 100644 --- a/lib/pages/mh_page/device/mht_blueteeth_device_page.dart +++ b/lib/pages/mh_page/device/mht_blueteeth_device_page.dart @@ -9,6 +9,7 @@ import 'package:flutter_svg/svg.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/BluetoothHelper.dart'; import 'package:vbvs_app/common/util/CommonVariables.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; @@ -62,6 +63,28 @@ class _MHTBlueteethDevicePageState extends State { mhtBlueToothController.startStatusPolling(); mhtBlueToothController.search.value = ""; mhtBlueToothController.currentDeviceMac?.value = ""; + // BluetoothHelper.listenBluetoothState((isOn) { + // if (!isOn && !_isDialogShowing) { + // _isDialogShowing = true; + // _showBluetoothNotEnabledDialog().then((_) { + // _isDialogShowing = false; + // }); + // } + // }); + BluetoothHelper.listenBluetoothState((isOn) { + mhtBlueToothController.model.bluetooth = isOn; + mhtBlueToothController.updateAll(); + + if (!isOn && !_isDialogShowing) { + _isDialogShowing = true; + mhtBlueToothController.model.blueRawData = []; + mhtBlueToothController.model.deviceDataStatus = []; + mhtBlueToothController.updateAll(); + _showBluetoothNotEnabledDialog().then((_) { + _isDialogShowing = false; + }); + } + }); } Future _checkBluetoothPermission() async { @@ -76,51 +99,6 @@ class _MHTBlueteethDevicePageState extends State { } } - // Future _requestBluetoothPermission() async { - // // showPermissionInfoDialog(Get.context!, CommonVariables().permissionInfo); - // // Map statuses = await [ - // // Permission.bluetoothScan, - // // Permission.bluetoothConnect, - // // Permission.location, - // // ].request(); - // Map statuses = {}; - // try { - // // 1️⃣ 先显示自定义提示弹窗 - // showPermissionInfoDialog(Get.context!, CommonVariables().permissionInfo); - - // // 2️⃣ 等待一小会,让 UI 有时间渲染提示弹窗 - // await Future.delayed(const Duration(milliseconds: 300)); - - // // 3️⃣ 再去申请权限(系统权限弹窗可能会弹出) - // statuses = await [ - // Permission.bluetoothScan, - // Permission.bluetoothConnect, - // Permission.location, - // ].request(); - - // // 这里你可以检查每个权限的状态 - // ef.log("权限状态: $statuses"); - // } catch (e) { - // ef.log("申请权限出错: $e"); - // } finally { - // // 4️⃣ 无论成功失败,最后关闭提示弹窗 - // if (Get.context != null) { - // Navigator.of(Get.context!, rootNavigator: true).pop(); - // } - // } - - // bool allGranted = statuses[Permission.bluetoothScan]?.isGranted == true && - // statuses[Permission.bluetoothConnect]?.isGranted == true && - // statuses[Permission.location]?.isGranted == true; - - // if (allGranted) { - // _startScanning(); - // _startPeriodicScan(); - // } else { - // _showPermissionDeniedDialog(); - // } - // } - Future _requestBluetoothPermission() async { Map statuses = {}; bool dialogShown = false; // 标记是否弹过权限提示弹窗 @@ -209,19 +187,12 @@ class _MHTBlueteethDevicePageState extends State { return; _scanSubscription?.cancel(); - var bluetoothState = await FlutterBluePlus.isOn; - mhtBlueToothController.model.bluetooth = bluetoothState; + // var bluetoothState = await FlutterBluePlus.isOn; + // bool isOn = await BluetoothHelper.isBluetoothOn(); + // mhtBlueToothController.model.bluetooth = isOn; mhtBlueToothController.updateAll(); - if (!bluetoothState && !_isDialogShowing) { - _isDialogShowing = true; - mhtBlueToothController.model.blueRawData = []; - mhtBlueToothController.model.deviceDataStatus = []; - mhtBlueToothController.updateAll(); - await _showBluetoothNotEnabledDialog(); - _isDialogShowing = false; - return; - } + if (!mhtBlueToothController.model.bluetooth!) return; if (!isScanning) { setState(() { @@ -230,66 +201,6 @@ class _MHTBlueteethDevicePageState extends State { await FlutterBluePlus.startScan(timeout: Duration(seconds: 10)); - // _scanSubscription = FlutterBluePlus.scanResults.listen((results) { - // if (!mounted) return; - - // final signalThreshold = mhtBlueToothController.model.singal!; - // final searchKey = - // mhtBlueToothController.search.value.trim().toLowerCase(); - - // final filteredResults = results.where((r) { - // final localName = r.advertisementData.localName; - // final isTarget = r.rssi > signalThreshold && - // isTargetDevice( - // localName, widget.deviceType['reg'].cast()); - // if (!isTarget) return false; - // final name = r.advertisementData.advName.toLowerCase(); - - // // String macAddress = r.device.remoteId.str; - // String macAddress = getDeviceId(r); - // final mac = macAddress.replaceAll(':', ''); - // final search = searchKey.trim().replaceAll(':', '').toLowerCase(); - - // if (search.isNotEmpty && - // !name.contains(search) && - // !mac.replaceAll(':', '').toLowerCase().contains(search)) { - // return false; - // } - - // return true; - // }).map((r) { - // return BlueToothDataModel.fromScanResult( - // r, widget.deviceType['type']?.toInt(), - // bind: false, - // name: r.advertisementData.localName, - // mac:getDeviceId(r).replaceAll(':', '')); - // }).toList(); - - // final currentDevices = mhtBlueToothController.model.blueRawData ?? []; - // final newDevices = []; - - // for (var newDevice in filteredResults) { - // // 检查设备是否已存在 - // final existingIndex = - // currentDevices.indexWhere((d) => d.mac == newDevice.mac); - - // if (existingIndex >= 0) { - // // 更新已有设备信息(如信号强度) - // currentDevices[existingIndex] = newDevice; - // } else { - // // 添加新设备 - // newDevices.add(newDevice); - // } - // } - - // setState(() { - // mhtBlueToothController.model.blueRawData = [ - // ...currentDevices, - // ...newDevices - // ]; - // }); - // }); - _scanSubscription = FlutterBluePlus.scanResults.listen((results) { if (!mounted) return; @@ -445,6 +356,7 @@ class _MHTBlueteethDevicePageState extends State { mhtBlueToothController.stopStatusPolling(); mhtBlueToothController.model.blueRawData = []; mhtBlueToothController.model.deviceDataStatus = []; + BluetoothHelper.cancelListener(); super.dispose(); } @@ -642,181 +554,6 @@ class _MHTBlueteethDevicePageState extends State { ), ), ), - // Container( - // width: double.infinity, - // decoration: BoxDecoration( - // color: themeController.currentColor.sc3, - // borderRadius: BorderRadius.circular(20.rpx), - // ), - // // child: Padding( - // // padding: EdgeInsetsDirectional.fromSTEB( - // // 35.rpx, 0, 35.rpx, 0), - // // child: Row( - // // mainAxisSize: MainAxisSize.max, - // // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // // children: [ - // // Expanded( - // // child: Row( - // // mainAxisSize: MainAxisSize.max, - // // children: [ - // // Padding( - // // padding: EdgeInsetsDirectional.fromSTEB( - // // 0, 0.rpx, 0, 0), - // // child: Container( - // // width: 25.rpx, - // // height: 25.rpx, - // // decoration: BoxDecoration(), - // // child: SvgPicture.asset( - // // 'assets/img/icon/query.svg', - // // fit: BoxFit.cover, - // // color: stringToColor("#333333"), - // // ), - // // ), - // // ), - // // Expanded( - // // child: Container( - // // width: 100.rpx, - // // height: 90.rpx, - // // decoration: BoxDecoration( - // // color: Colors.white, - // // ), - // // child: Align( - // // alignment: - // // AlignmentDirectional(-1, 0), - // // child: TextFormField( - // // initialValue: - // // mhtBlueToothController - // // .search.value, - // // onChanged: (Value) { - // // mhtBlueToothController - // // .search.value = Value; - // // }, - // // autofocus: false, - // // obscureText: false, - // // decoration: InputDecoration( - // // isDense: true, - // // labelStyle: TextStyle( - // // fontFamily: 'Inter', - // // fontSize: 26.rpx, - // // letterSpacing: 0.0, - // // ), - // // hintText: '检索设备'.tr, - // // hintStyle: TextStyle( - // // fontFamily: 'Inter', - // // fontSize: 26.rpx, - // // letterSpacing: 0.0, - // // ), - // // enabledBorder: - // // OutlineInputBorder( - // // borderSide: BorderSide( - // // color: Color(0x00000000), - // // width: 1.rpx, - // // ), - // // borderRadius: - // // BorderRadius.circular( - // // 8.rpx), - // // ), - // // focusedBorder: - // // OutlineInputBorder( - // // borderSide: BorderSide( - // // color: Color(0x00000000), - // // width: 1.rpx, - // // ), - // // borderRadius: - // // BorderRadius.circular( - // // 8.rpx), - // // ), - // // errorBorder: OutlineInputBorder( - // // borderSide: BorderSide( - // // color: Colors.red, - // // width: 1.rpx, - // // ), - // // borderRadius: - // // BorderRadius.circular( - // // 8.rpx), - // // ), - // // focusedErrorBorder: - // // OutlineInputBorder( - // // borderSide: BorderSide( - // // color: Colors.red, - // // width: 1.rpx, - // // ), - // // borderRadius: - // // BorderRadius.circular( - // // 8.rpx), - // // ), - // // filled: false, - // // fillColor: themeController - // // .currentColor.sc22, - // // ), - // // style: TextStyle( - // // fontFamily: 'Inter', - // // fontSize: 26.rpx, - // // letterSpacing: 0.0, - // // ), - // // cursorColor: - // // stringToColor("#003058"), - // // ), - // // ), - // // ), - // // ), - // // ].divide(SizedBox(width: 6.rpx)), - // // ), - // // ), - // // Padding( - // // padding: EdgeInsetsDirectional.fromSTEB( - // // 26.rpx, 0, 0, 0), - // // child: Row( - // // mainAxisSize: MainAxisSize.max, - // // children: [ - // // SizedBox( - // // height: 50.rpx, - // // child: VerticalDivider( - // // thickness: 2.rpx, - // // color: stringToColor("#333333"), - // // ), - // // ), - // // ClickableContainer( - // // backgroundColor: Colors.transparent, - // // highlightColor: - // // themeController.currentColor.sc4, - // // borderRadius: 6.rpx, - // // padding: EdgeInsets.zero, - // // onTap: () async { - // // _startScanning(); - // // }, - // // child: Text( - // // '搜索'.tr, - // // style: TextStyle( - // // fontFamily: 'Inter', - // // fontSize: 30.rpx, - // // letterSpacing: 0.0, - // // color: stringToColor("#333333"), - // // ), - // // ), - // // ), - // // ].divide(SizedBox(width: 26.rpx)), - // // ), - // // ), - // // ], - // // ), - // // ), - // child: Padding( - // padding: - // EdgeInsetsDirectional.fromSTEB(0, 10, 0, 23), - // child: SearchWidget( - // keyword: mhtBlueToothController.search.value, - // color: Colors.red, - // hint: "检索设备", - // onChange: (d) { - // mhtBlueToothController.search.value = d; - // }, - // findCallback: () { - // // controller.getDeviceList(); - // }, - // ), - // ), - // ), Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0), child: SearchWidget( diff --git a/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart b/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart index e9d0d62..5dcec22 100644 --- a/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart +++ b/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart @@ -93,20 +93,53 @@ class _HomeDeviceStausWidgetState extends State { onTap: () async { try { var device = widget.deviceStatus; - WebviewTestController webviewTestController = Get.find(); + webviewTestController.web.jsbridge?.dart.switchLanguage( mhLanguageController .selectLanguage.value!.language_code); + await checkBlueToothPermissin(); + webviewTestController.web.jsbridge?.dart .pageActive(false); + await Future.delayed(Duration(seconds: 1)); - webviewTestController.web.jsbridge?.dart - .appToHtmlDevice(device); + MainPageBBottomChange.jumpTo(2); + + // 🔹 重试调用 appToHtmlDevice + int attempt = 0; + const int maxAttempts = 10; + bool success = false; + + while (attempt < maxAttempts && !success) { + try { + bool? flag = await webviewTestController + .web.jsbridge?.dart + .appToHtmlDevice(device); + + if (flag == true) { + success = true; // 成功,跳出循环 + } else { + ef.log( + "appToHtmlDevice 返回 false,第 ${attempt + 1} 次重试"); + } + } catch (e) { + ef.log("appToHtmlDevice 异常,第 ${attempt + 1} 次重试: $e"); + } + + attempt++; + if (!success) { + await Future.delayed(Duration(seconds: 1)); + } + } + + if (!success) { + ef.log("appToHtmlDevice 超过最大重试次数 $maxAttempts,调用失败"); + } } catch (e) { - DailyLogUtils.writeError("发生异常: $e"); + DailyLogUtils.writeError("进入控制页发生异常: $e"); } }, colors: