更新ios蓝牙开关判定
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
[
|
||||
"assets/miniapp/mhtControl_1.0.69.zip"
|
||||
"assets/miniapp/mhtControl_1.0.74.zip"
|
||||
]
|
||||
Binary file not shown.
39
lib/common/util/BluetoothHelper.dart
Normal file
39
lib/common/util/BluetoothHelper.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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<MHTBlueteethDevicePage> {
|
||||
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<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 {
|
||||
Map<Permission, PermissionStatus> statuses = {};
|
||||
bool dialogShown = false; // 标记是否弹过权限提示弹窗
|
||||
@@ -209,19 +187,12 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
|
||||
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<MHTBlueteethDevicePage> {
|
||||
|
||||
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) {
|
||||
if (!mounted) return;
|
||||
|
||||
@@ -445,6 +356,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
|
||||
mhtBlueToothController.stopStatusPolling();
|
||||
mhtBlueToothController.model.blueRawData = [];
|
||||
mhtBlueToothController.model.deviceDataStatus = [];
|
||||
BluetoothHelper.cancelListener();
|
||||
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: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
|
||||
child: SearchWidget(
|
||||
|
||||
@@ -93,20 +93,53 @@ class _HomeDeviceStausWidgetState extends State<HomeDeviceStausWidget> {
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user