更新ios蓝牙开关判定

This commit is contained in:
wyf
2025-09-01 09:47:58 +08:00
parent 0fc0cf6c6b
commit 8536cb61f8
5 changed files with 105 additions and 296 deletions

View File

@@ -1,3 +1,3 @@
[ [
"assets/miniapp/mhtControl_1.0.69.zip" "assets/miniapp/mhtControl_1.0.74.zip"
] ]

View File

@@ -0,0 +1,39 @@
import 'dart:async';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
class BluetoothHelper {
static StreamSubscription<BluetoothAdapterState>? _subscription;
/// 获取当前蓝牙是否开启(跨平台封装)
static Future<bool> 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;
}
}

View File

@@ -9,6 +9,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:vbvs_app/common/color/appConstants.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/CommonVariables.dart';
import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/common/util/MyUtils.dart';
@@ -62,6 +63,28 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
mhtBlueToothController.startStatusPolling(); mhtBlueToothController.startStatusPolling();
mhtBlueToothController.search.value = ""; mhtBlueToothController.search.value = "";
mhtBlueToothController.currentDeviceMac?.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<void> _checkBluetoothPermission() async { Future<void> _checkBluetoothPermission() async {
@@ -76,51 +99,6 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
} }
} }
// Future<void> _requestBluetoothPermission() async {
// // showPermissionInfoDialog(Get.context!, CommonVariables().permissionInfo);
// // Map<Permission, PermissionStatus> statuses = await [
// // Permission.bluetoothScan,
// // Permission.bluetoothConnect,
// // Permission.location,
// // ].request();
// Map<Permission, PermissionStatus> 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<void> _requestBluetoothPermission() async { Future<void> _requestBluetoothPermission() async {
Map<Permission, PermissionStatus> statuses = {}; Map<Permission, PermissionStatus> statuses = {};
bool dialogShown = false; // 标记是否弹过权限提示弹窗 bool dialogShown = false; // 标记是否弹过权限提示弹窗
@@ -209,19 +187,12 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
return; return;
_scanSubscription?.cancel(); _scanSubscription?.cancel();
var bluetoothState = await FlutterBluePlus.isOn; // var bluetoothState = await FlutterBluePlus.isOn;
mhtBlueToothController.model.bluetooth = bluetoothState; // bool isOn = await BluetoothHelper.isBluetoothOn();
// mhtBlueToothController.model.bluetooth = isOn;
mhtBlueToothController.updateAll(); mhtBlueToothController.updateAll();
if (!bluetoothState && !_isDialogShowing) { if (!mhtBlueToothController.model.bluetooth!) return;
_isDialogShowing = true;
mhtBlueToothController.model.blueRawData = [];
mhtBlueToothController.model.deviceDataStatus = [];
mhtBlueToothController.updateAll();
await _showBluetoothNotEnabledDialog();
_isDialogShowing = false;
return;
}
if (!isScanning) { if (!isScanning) {
setState(() { setState(() {
@@ -230,66 +201,6 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
await FlutterBluePlus.startScan(timeout: Duration(seconds: 10)); 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<String>());
// 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 = <BlueToothDataModel>[];
// 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) { _scanSubscription = FlutterBluePlus.scanResults.listen((results) {
if (!mounted) return; if (!mounted) return;
@@ -445,6 +356,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
mhtBlueToothController.stopStatusPolling(); mhtBlueToothController.stopStatusPolling();
mhtBlueToothController.model.blueRawData = []; mhtBlueToothController.model.blueRawData = [];
mhtBlueToothController.model.deviceDataStatus = []; mhtBlueToothController.model.deviceDataStatus = [];
BluetoothHelper.cancelListener();
super.dispose(); super.dispose();
} }
@@ -642,181 +554,6 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
), ),
), ),
), ),
// 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(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0), padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
child: SearchWidget( child: SearchWidget(

View File

@@ -93,20 +93,53 @@ class _HomeDeviceStausWidgetState extends State<HomeDeviceStausWidget> {
onTap: () async { onTap: () async {
try { try {
var device = widget.deviceStatus; var device = widget.deviceStatus;
WebviewTestController webviewTestController = Get.find(); WebviewTestController webviewTestController = Get.find();
webviewTestController.web.jsbridge?.dart.switchLanguage( webviewTestController.web.jsbridge?.dart.switchLanguage(
mhLanguageController mhLanguageController
.selectLanguage.value!.language_code); .selectLanguage.value!.language_code);
await checkBlueToothPermissin(); await checkBlueToothPermissin();
webviewTestController.web.jsbridge?.dart webviewTestController.web.jsbridge?.dart
.pageActive(false); .pageActive(false);
await Future.delayed(Duration(seconds: 1)); await Future.delayed(Duration(seconds: 1));
webviewTestController.web.jsbridge?.dart
.appToHtmlDevice(device);
MainPageBBottomChange.jumpTo(2); 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) { } catch (e) {
DailyLogUtils.writeError("发生异常: $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");
} }
}, },
colors: colors: