Browse Source

上传代码

newdev_shunjiawei
liwei1dao 1 year ago
parent
commit
f24cc654b8
  1. 14
      lib/data/services/ble_manager.dart
  2. 162
      lib/modules/pairing/controllers/pairing_controller.dart
  3. 240
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift
  4. 14
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift
  5. 38
      local_plugins/ble_service/lib/ble_service.dart

14
lib/data/services/ble_manager.dart

@ -782,9 +782,19 @@ class BleManager extends GetxService {
} }
} }
Future<Map<String, String>?> getDeviceInfo(String address) async { Future<Map<String, String>?> getDeviceInfo(String deviceName) async {
try { try {
final result = _bleService.getDeviceInfo(address); final result = _bleService.getDeviceInfo(deviceName);
return result;
} catch (e) {
Logger.error('获取设备信息: ${e.toString()}');
return null;
}
}
Future<List<Map<String, String>>?> getDeviceList(String deviceName) async {
try {
final result = _bleService.getDeviceList(deviceName);
return result; return result;
} catch (e) { } catch (e) {
Logger.error('获取设备信息: ${e.toString()}'); Logger.error('获取设备信息: ${e.toString()}');

162
lib/modules/pairing/controllers/pairing_controller.dart

@ -1,3 +1,6 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:app_settings/app_settings.dart'; import 'package:app_settings/app_settings.dart';
import '/data/models/appconfig.dart'; import '/data/models/appconfig.dart';
import '/data/models/user_Info.dart'; import '/data/models/user_Info.dart';
@ -11,6 +14,7 @@ import '../../../core/utils/logger.dart';
import 'dart:io'; import 'dart:io';
import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/bluetooth_manager.dart';
import '../../../data/services/ble_manager.dart'; import '../../../data/services/ble_manager.dart';
import '../../../core/utils/permission_util.dart';
/// 配对状态枚举 - 简化版本 /// 配对状态枚举 - 简化版本
enum PairingState { enum PairingState {
@ -414,16 +418,34 @@ class PairingController extends GetxController {
/// 检查权限 /// 检查权限
Future<bool> _checkPermissions() async { Future<bool> _checkPermissions() async {
// Android 平台权限检查 // Android权限检查
Map<Permission, PermissionStatus> statuses = await [ if (Platform.isAndroid) {
Permission.bluetoothScan, Logger.i(_tag, '开始检查Android权限');
Permission.bluetoothConnect, // 检查蓝牙相关权限
Permission.locationWhenInUse, final bluetoothScanGranted =
].request(); await PermissionUtil.instance.requestPermission(
permissionType: Permission.bluetoothScan,
permissionName: 'bluetoothScan'.tr,
explanationText: 'bluetoothScanExplanation'.tr,
permanentDenialText: 'bluetoothScanPermanentDenial'.tr,
);
final bluetoothConnectGranted =
await PermissionUtil.instance.requestPermission(
permissionType: Permission.bluetoothConnect,
permissionName: 'bluetoothConnect'.tr,
explanationText: 'bluetoothConnectExplanation'.tr,
permanentDenialText: 'bluetoothConnectPermanentDenial'.tr,
);
final locationGranted = await PermissionUtil.instance.requestPermission(
permissionType: Permission.locationWhenInUse,
permissionName: 'locationInfo'.tr,
explanationText: 'locationForBluetoothExplanation'.tr,
permanentDenialText: 'locationPermanentDenial'.tr,
);
return statuses[Permission.bluetoothScan]!.isGranted && return bluetoothScanGranted && bluetoothConnectGranted && locationGranted;
statuses[Permission.bluetoothConnect]!.isGranted && }
statuses[Permission.locationWhenInUse]!.isGranted; return true;
} }
/// 验证设备 /// 验证设备
@ -566,13 +588,8 @@ class PairingController extends GetxController {
//自动绑定设备 0 未合作商 1 合作商 2,已绑定 //自动绑定设备 0 未合作商 1 合作商 2,已绑定
Future<int> authbindingDevice(BluetoothDevice device) async { Future<int> authbindingDevice(BluetoothDevice device) async {
if (User.instance.earphonelicense != "" && // 检查是否已经绑定
User.instance.earphonemac == device.address) { if (User.instance.earphonemac == device.address) {
// 已经绑定
return 10;
}
if (User.instance.earphoneauthcode != "" &&
User.instance.earphonemac == device.address) {
// 已经绑定 // 已经绑定
return 9; return 9;
} }
@ -580,51 +597,124 @@ class PairingController extends GetxController {
final deviceName = device.name; final deviceName = device.name;
final names = AppConfig.allproductNames(); final names = AppConfig.allproductNames();
print('获取到 deviceName: $deviceName names:$names'); print(
'获取到 deviceName: $deviceName address: ${device.address} names:$names');
if (names.contains(deviceName)) { if (names.contains(deviceName)) {
await _bleManager.startScan(deviceName); await _bleManager.startScan(deviceName);
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
// 尝试最多读取 3 次设备信息,每次间隔 1 秒 // 尝试最多读取 3 次设备信息,每次间隔 1 秒
Map<String, String>? deviceinfo; List<Map<String, String>>? deviceinfos;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
deviceinfo = await _bleManager.getDeviceInfo(device.address); // 使用设备名称获取设备列表
print('获取到 deviceinfo: $deviceinfo'); deviceinfos = await _bleManager.getDeviceList(deviceName);
if (deviceinfo != null) { print('获取到 deviceinfos: $deviceinfos');
break;
if (deviceinfos != null && deviceinfos.isNotEmpty) {
// 循环读取每个设备的hex数据
for (var deviceInfo in deviceinfos) {
String? hexData = deviceInfo["hex"];
if (hexData != null && hexData.length >= 28) {
// 确保hex数据长度足够(14字节 = 28个字符)
// 读取9-14字节的MAC地址
String macFromHex = extractMacFromHex(hexData, device.address);
if (macFromHex.isNotEmpty) {
String code = "";
// 找到匹配的设备,提取授权码
if (Platform.isIOS) {
// iOS设备,提取13-22字节的授权码
code = extractAndReverseBytes(hexData, 13, 22);
print('找到匹配设备,获取到 code: $code');
if (code != "") {
deviceCode.value = code;
return 1;
} }
await Future.delayed(Duration(seconds: 1)); } else if (Platform.isAndroid) {
// Android设备,提取15-24字节的授权码
code = extractAndReverseBytes(hexData, 15, 24);
} }
print('获取到 deviceinfo: $deviceinfo'); print('找到匹配设备,获取到 code: $code');
if (deviceinfo != null) {
// final code = processHex(deviceinfo["hex"]!, 15, 25);
String code = extractAndReverseBytes(deviceinfo["hex"]!, 15, 24);
print('获取到 code: $code');
// 安全检查长度
if (code != "") { if (code != "") {
deviceCode.value = code; deviceCode.value = code;
return 1; return 1;
} else {
return 0;
} }
} }
}
}
}
await Future.delayed(Duration(seconds: 1));
}
return 0; return 0;
// 调用BLE管理器的自动绑定方法
} else { } else {
return 0; return 0;
} }
} }
// 新增方法:从hex数据中提取MAC地址并与当前设备MAC对比
String extractMacFromHex(String hexData, String deviceMac) {
try {
// 将hex字符串转换为字节数组
List<int> bytes = [];
for (int i = 0; i < hexData.length; i += 2) {
bytes.add(int.parse(hexData.substring(i, i + 2), radix: 16));
}
// 读取9-14字节(索引8-13)的MAC地址
if (bytes.length < 14) {
return "";
}
List<int> macBytes = [];
if (Platform.isIOS) {
for (int i = 7; i <= 12; i++) {
// 每个字节异或0x5A
int decodedByte = bytes[i] ^ 0x5A;
macBytes.add(decodedByte);
}
} else if (Platform.isAndroid) {
for (int i = 9; i <= 14; i++) {
// 每个字节异或0x5A
int decodedByte = bytes[i] ^ 0x5A;
macBytes.add(decodedByte);
}
}
// 将MAC字节转换为MAC地址字符串格式
String extractedMac = macBytes
.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase())
.join(':');
// 格式化当前设备MAC地址(确保格式一致)
String formattedDeviceMac = deviceMac.replaceAll(':', '').toUpperCase();
String formattedExtractedMac =
extractedMac.replaceAll(':', '').toUpperCase();
print('设备MAC: $deviceMac, 提取的MAC: $extractedMac');
// 对比MAC地址
if (formattedDeviceMac == formattedExtractedMac) {
print('MAC地址匹配成功!');
return extractedMac;
} else {
print('MAC地址不匹配');
return "";
}
} catch (e) {
print('提取MAC地址时出错: $e');
return "";
}
}
//确认绑定设备 //确认绑定设备
void confirmBindDevice() async { void confirmBindDevice() async {
final response = await Api.bindearphone({ final response = await Api.bindearphone({
"code": deviceCode.value, "code": deviceCode.value,
"earphonname": currentDevice?.name, "earphonname": currentDevice?.name,
"earphonemac": currentDevice?.address, "earphonemac": currentDevice?.address, // 使用 address 替代 deviceId
}); });
Logger.i(_tag, '手动授权结果 ${response}'); Logger.i(_tag, '手动授权结果 ${response}');
if (response != null) { if (response != null) {
Logger.i(_tag, '绑定设备成功'); Logger.i(_tag, '绑定设备成功');
User.instance.earphonemac = currentDevice?.address ?? ''; User.instance.earphonemac = currentDevice?.address ?? ''; // 使用 address
User.instance.earphonename = currentDevice?.name ?? ''; User.instance.earphonename = currentDevice?.name ?? '';
User.instance.earphonelicense = deviceCode.value; User.instance.earphonelicense = deviceCode.value;
_transition(PairingState.verifying); _transition(PairingState.verifying);
@ -660,11 +750,11 @@ class PairingController extends GetxController {
final response = await Api.bindauthcode({ final response = await Api.bindauthcode({
"code": codeInputController.text.trim(), "code": codeInputController.text.trim(),
"earphonname": currentDevice?.name, "earphonname": currentDevice?.name,
"earphonemac": currentDevice?.address, "earphonemac": currentDevice?.address, // 使用 address 替代 deviceId
}); });
Logger.i(_tag, '手动授权结果 ${response}'); Logger.i(_tag, '手动授权结果 ${response}');
if (response != null) { if (response != null) {
User.instance.earphonemac = currentDevice?.address ?? ''; User.instance.earphonemac = currentDevice?.address ?? ''; // 使用 address
User.instance.earphonename = currentDevice?.name ?? ''; User.instance.earphonename = currentDevice?.name ?? '';
User.instance.earphoneauthcode = codeInputController.text.trim(); User.instance.earphoneauthcode = codeInputController.text.trim();
_transition(PairingState.verifying); _transition(PairingState.verifying);

240
local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift

@ -165,31 +165,32 @@ public class BleService: NSObject {
} }
/// 开始扫描BLE设备 /// 开始扫描BLE设备
public func startScan(timeout: TimeInterval = 30.0) { public func startScan(timeout: TimeInterval = 30.0) -> Bool {
if centralManager == nil { if centralManager == nil {
initializeCentralManager() initializeCentralManager()
} }
guard let manager = centralManager, manager.state == .poweredOn else { guard let manager = centralManager, manager.state == .poweredOn else {
os_log("❌ 蓝牙未就绪,无法开始扫描", log: logger, type: .error) os_log("❌ 蓝牙未就绪,无法开始扫描", log: logger, type: .error)
return return false
} }
if isScanning { if isScanning {
stopScan() return true
} }
// 清空之前的扫描结果 // 清空之前的扫描结果
discoveredDevices.removeAll() discoveredDevices.removeAll()
deviceAdvertisementData.removeAll()
isScanning = true isScanning = true
let serviceUUIDs = [BleConst.PRIMARY_SERVICE_UUID, BleConst.AUDIO_SERVICE_UUID] // 移除服务UUID过滤,扫描所有设备
manager.scanForPeripherals(withServices: serviceUUIDs, options: [ manager.scanForPeripherals(withServices: nil, options: [
CBCentralManagerScanOptionAllowDuplicatesKey: false CBCentralManagerScanOptionAllowDuplicatesKey: true // 允许重复以获取更新的广播数据
]) ])
os_log("🔍 开始扫描BLE设备,超时时间: %.1f秒", log: logger, type: .info, timeout) os_log("🔍 开始扫描所有BLE设备(无过滤),超时时间: %.1f秒", log: logger, type: .info, timeout)
// 设置扫描超时 // 设置扫描超时
scanTimer?.invalidate() scanTimer?.invalidate()
@ -197,6 +198,7 @@ public class BleService: NSObject {
self?.stopScan() self?.stopScan()
os_log("⏰ 扫描超时,自动停止", log: self?.logger ?? OSLog.default, type: .info) os_log("⏰ 扫描超时,自动停止", log: self?.logger ?? OSLog.default, type: .info)
} }
return true
} }
/// 停止扫描 /// 停止扫描
@ -206,7 +208,20 @@ public class BleService: NSObject {
isScanning = false isScanning = false
scanTimer?.invalidate() scanTimer?.invalidate()
scanTimer = nil scanTimer = nil
os_log("⏹️ 停止BLE扫描", log: logger, type: .info)
// let deviceCount = discoveredDevices.count
// os_log("⏹️ 停止BLE扫描,共发现 %d 个设备", log: logger, type: .info, deviceCount)
//
// // 打印所有发现的设备摘要
// if deviceCount > 0 {
// os_log("📋 扫描结果摘要:", log: logger, type: .info)
// for (index, deviceInfo) in discoveredDevices.values.enumerated() {
// if let name = deviceInfo["name"] as? String,
// let rssi = deviceInfo["rssi"] as? Int {
// os_log("📋 %d. %{public}@ (RSSI: %d)", log: logger, type: .info, index + 1, name, rssi)
// }
// }
// }
} }
} }
@ -331,6 +346,75 @@ public class BleService: NSObject {
return Array(discoveredDevices.values) return Array(discoveredDevices.values)
} }
/// 根据设备名称获取设备列表
public func getDeviceAdvertisementData(deviceName: String) -> [[String: Any]] {
var matchingDevices: [[String: Any]] = []
// 遍历所有已发现的设备,查找匹配的设备名
for (deviceId, deviceInfo) in discoveredDevices {
if let name = deviceInfo["name"] as? String, name == deviceName {
// 获取对应的广播数据
var deviceData = deviceInfo
if let advData = deviceAdvertisementData[deviceId] {
// 合并设备信息和广播数据
deviceData.merge(advData) { (current, _) in current }
}
matchingDevices.append(deviceData)
}
}
os_log("根据设备名 '%{public}@' 找到 %d 个匹配设备", log: logger, type: .debug, deviceName, matchingDevices.count)
return matchingDevices
}
/// 获取设备的制造商数据(hex格式)
public func getDeviceManufacturerDataHex(deviceId: String) -> String? {
guard let advData = deviceAdvertisementData[deviceId],
let manufacturerData = advData["manufacturerDataRaw"] as? Data else {
return nil
}
return manufacturerData.map { String(format: "%02x", $0) }.joined(separator: " ")
}
/// 获取所有设备的广播数据摘要
public func getAllDevicesAdvertisementData() -> [String: [String: Any]] {
return deviceAdvertisementData
}
/// 获取设备信息
public func getDeviceInfo(deviceId: String) -> [String: Any]? {
// 直接从缓存获取,与 Android 端逻辑保持一致
if let cachedInfo = discoveredDevices[deviceId] {
os_log("获取设备信息: %{public}@", log: logger, type: .debug, deviceId)
return cachedInfo
}
os_log("未找到设备信息: %{public}@", log: logger, type: .error, deviceId)
return nil
}
/// 清除过期的设备缓存(超过maxCacheTime的设备)
public func clearExpiredDevices() {
let currentTime = Date().timeIntervalSince1970
let expiredDeviceIds = deviceAdvertisementData.compactMap { (deviceId, advData) -> String? in
if let timestamp = advData["timestamp"] as? TimeInterval,
currentTime - timestamp > maxCacheTime {
return deviceId
}
return nil
}
for deviceId in expiredDeviceIds {
discoveredDevices.removeValue(forKey: deviceId)
deviceAdvertisementData.removeValue(forKey: deviceId)
os_log("🗑️ 清除过期设备缓存: %{public}@", log: logger, type: .debug, deviceId)
}
if !expiredDeviceIds.isEmpty {
os_log("🗑️ 已清除%d个过期设备缓存", log: logger, type: .info, expiredDeviceIds.count)
}
}
// MARK: - 回调通知方法 // MARK: - 回调通知方法
/// 通知所有回调扫描结果 /// 通知所有回调扫描结果
@ -1053,76 +1137,118 @@ extension BleService: CBCentralManagerDelegate {
} }
} }
// 原有方法
public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
let deviceId = peripheral.identifier.uuidString let deviceId = peripheral.identifier.uuidString
let deviceName = peripheral.name ?? "Unknown" let deviceName = peripheral.name ?? "Unknown"
// 构建设备基本信息 // 简化的设备信息构建 - 参考 Android 端的简洁性
var deviceInfo: [String: Any] = [ let deviceInfo = buildDeviceInfo(peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
"name": deviceName,
"id": deviceId,
"rssi": RSSI.intValue,
"discoveredAt": Date().timeIntervalSince1970
]
// 详细的广播数据记录 // 检查是否为新设备或信息有重要变化
var advData: [String: Any] = [:] var shouldNotify = false
// 制造商数据 if let existingDevice = discoveredDevices[deviceId] {
if let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data { // 设备已存在,检查是否有重要变化
deviceInfo["manufacturerData"] = manufacturerData let oldRssi = existingDevice["rssi"] as? Int ?? 0
advData["manufacturerData"] = manufacturerData.map { String(format: "%02x", $0) }.joined(separator: " ") let newRssi = RSSI.intValue
advData["manufacturerDataRaw"] = manufacturerData
}
// 服务UUID列表 // 只有当RSSI变化超过阈值时才上报(避免频繁更新)
if let serviceUUIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] { if abs(newRssi - oldRssi) > 10 {
let serviceUUIDStrings = serviceUUIDs.map { $0.uuidString } shouldNotify = true
deviceInfo["serviceUUIDs"] = serviceUUIDStrings os_log("📱 设备RSSI变化较大 - 名称: %{public}@, UUID: %{public}@, RSSI: %d → %d", log: logger, type: .debug, deviceName, deviceId, oldRssi, newRssi)
advData["serviceUUIDs"] = serviceUUIDStrings
} }
} else {
// 新设备,需要上报
shouldNotify = true
os_log("📱 发现新设备 - 名称: %{public}@, UUID: %{public}@", log: logger, type: .info, deviceName, deviceId)
// 本地名称 // 打印 hex 数据 - 直接从 deviceInfo 获取
if let localName = advertisementData[CBAdvertisementDataLocalNameKey] as? String { if let hex = deviceInfo["hex"] as? String {
advData["localName"] = localName os_log("📡 设备 hex 数据: %{public}@", log: logger, type: .info, hex)
} }
// 发射功率
if let txPowerLevel = advertisementData[CBAdvertisementDataTxPowerLevelKey] as? NSNumber {
advData["txPowerLevel"] = txPowerLevel.intValue
} }
// 服务数据 // 更新缓存(无论是否上报都要更新)
if let serviceData = advertisementData[CBAdvertisementDataServiceDataKey] as? [CBUUID: Data] { discoveredDevices[deviceId] = deviceInfo
var serviceDataDict: [String: String] = [:]
for (uuid, data) in serviceData { // 只有在需要时才上报
serviceDataDict[uuid.uuidString] = data.map { String(format: "%02x", $0) }.joined(separator: " ") if shouldNotify {
notifyScanResult(devices: [deviceInfo])
} }
advData["serviceData"] = serviceDataDict
} }
// 可连接性 // 新增:统一的设备信息构建方法
if let isConnectable = advertisementData[CBAdvertisementDataIsConnectable] as? NSNumber { private func buildDeviceInfo(peripheral: CBPeripheral, advertisementData: [String: Any], rssi: NSNumber) -> [String: Any] {
advData["isConnectable"] = isConnectable.boolValue let deviceId = peripheral.identifier.uuidString
let deviceName = peripheral.name ?? "Unknown"
// 基本设备信息 - 与 Android 端格式对齐
var deviceInfo: [String: Any] = [
"id": deviceId,
"name": deviceName,
"rssi": rssi.intValue,
"discoveredAt": Date().timeIntervalSince1970
]
// 服务 UUIDs - 与 Android 端保持一致的字段名
if let serviceUUIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] {
let uuids = serviceUUIDs.map { $0.uuidString }
deviceInfo["uuids"] = uuids // 使用与 Android 端一致的字段名
} }
// 完整的广播数据 // 只存储 hex 数据 - 简化存储
advData["rssi"] = RSSI.intValue if let rawData = extractRawAdvertisementData(from: advertisementData) {
advData["timestamp"] = Date().timeIntervalSince1970 deviceInfo["hex"] = rawData // 直接存储 hex 数据,不使用 advertisementData 包装
}
// 缓存设备信息和广播数据 return deviceInfo
discoveredDevices[deviceId] = deviceInfo }
deviceAdvertisementData[deviceId] = advData
// 添加广播数据到设备信息中 // 提取原始广播数据的辅助方法
deviceInfo["advertisementData"] = advData private func extractRawAdvertisementData(from advertisementData: [String: Any]) -> String? {
// 尝试从各种数据源构建原始数据的十六进制表示
var allData = Data()
os_log("📡 发现设备: %{public}@ (ID: %{public}@), RSSI: %d", log: logger, type: .info, deviceName, deviceId, RSSI.intValue) if let manufacturerData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data {
os_log("📡 广播数据: %{public}@", log: logger, type: .debug, String(describing: advData)) allData.append(manufacturerData)
}
// 报告给回调 if let serviceData = advertisementData[CBAdvertisementDataServiceDataKey] as? [CBUUID: Data] {
notifyScanResult(devices: [deviceInfo]) for (_, data) in serviceData {
allData.append(data)
}
}
return allData.isEmpty ? nil : allData.map { String(format: "%02X", $0) }.joined()
}
// 数据清理方法
private func sanitizeData(_ dict: [String: Any]) -> [String: Any] {
var sanitized: [String: Any] = [:]
for (key, value) in dict {
if value is Data {
// 跳过 Data 对象
continue
} else if let nestedDict = value as? [String: Any] {
sanitized[key] = sanitizeData(nestedDict)
} else if let array = value as? [Any] {
var filteredArray: [Any] = []
for item in array {
if item is Data {
// 跳过 Data 对象
continue
} else if let nestedDict = item as? [String: Any] {
filteredArray.append(sanitizeData(nestedDict))
} else {
filteredArray.append(item)
}
}
sanitized[key] = filteredArray
} else {
sanitized[key] = value
}
}
return sanitized
} }
public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

14
local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftBleServicePlugin.swift

@ -118,6 +118,12 @@ public class SwiftBleServicePlugin: NSObject, FlutterPlugin {
os_log("⏹️ 停止BLE扫描", log: logger, type: .info) os_log("⏹️ 停止BLE扫描", log: logger, type: .info)
BleService.shared.stopScan() BleService.shared.stopScan()
result(true) result(true)
case "getDeviceList":
let arguments = call.arguments as? [String: Any]
let deviceName = (arguments?["deviceName"] as? String) ?? ""
os_log("🔍 查询设备信息,deviceName: %s", log: logger, type: .info, deviceName)
let info = BleService.shared.getDeviceAdvertisementData(deviceName: deviceName)
result(info)
case "connectToDevice": case "connectToDevice":
let arguments = call.arguments as? [String: Any] let arguments = call.arguments as? [String: Any]
@ -127,14 +133,12 @@ public class SwiftBleServicePlugin: NSObject, FlutterPlugin {
details: nil)) details: nil))
return return
} }
os_log("🔗 连接到设备: %@", log: logger, type: .info, deviceId) os_log("🔗 连接到设备: %@", log: logger, type: .info, deviceId)
let success = BleService.shared.connectToDevice(uuid: deviceId) let success = BleService.shared.connectToDevice(uuid: deviceId)
result(success) result(success)
case "clearExpiredDevices":
case "getDiscoveredDevices": BleService.shared.clearExpiredDevices()
let devices = BleService.shared.getDiscoveredDevices() result(true)
result(devices)
case "requestBluetoothPermission": case "requestBluetoothPermission":
// 移除这个方法调用,让iOS系统自然处理权限 // 移除这个方法调用,让iOS系统自然处理权限

38
local_plugins/ble_service/lib/ble_service.dart

@ -293,16 +293,19 @@ class BleService {
} }
} }
/// 断开连接 /// 获取设备信息
Future<Map<String, String>?> getDeviceInfo(String address) async { Future<Map<String, String>?> getDeviceInfo(String deviceName) async {
try { try {
final result = await _methodChannel final result = await _methodChannel
.invokeMethod<Map>('getDeviceInfo', {'address': address}); .invokeMethod<Map>('getDeviceInfo', {'deviceName': deviceName});
print('获取设备信息!: $result'); print('获取设备信息!: $result');
if (result != null) { if (result != null) {
return { return {
'name': result['name'] ?? "未知", 'name': result['name'] ?? "未知",
'address': result['address'] ?? "", 'address': result['address'] ?? "",
'id': result['id'] ??
result['address'] ??
"", // iOS 返回 UUID,Android 返回 address
'hex': result['hex'] ?? "", 'hex': result['hex'] ?? "",
}; };
} else { } else {
@ -314,6 +317,32 @@ class BleService {
} }
} }
/// 获取设备列表(通过设备名)
Future<List<Map<String, String>>?> getDeviceList(String deviceName) async {
try {
final result = await _methodChannel
.invokeMethod<List>('getDeviceList', {'deviceName': deviceName});
print('获取设备列表!: $result');
if (result != null) {
return result.map<Map<String, String>>((device) {
return {
'name': device['name'] ?? "未知",
'address': device['address'] ?? "",
'id': device['id'] ??
device['address'] ??
"", // iOS 返回 UUID,Android 返回 address
'hex': device['hex'] ?? "",
};
}).toList();
} else {
return null;
}
} catch (e) {
print('获取设备列表失败!: $e');
return null;
}
}
/// 注册BLE后台扫描 /// 注册BLE后台扫描
/// ///
/// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用 /// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用
@ -439,7 +468,8 @@ class BleService {
/// 请求蓝牙权限(仅iOS) /// 请求蓝牙权限(仅iOS)
Future<bool> requestBluetoothPermission() async { Future<bool> requestBluetoothPermission() async {
try { try {
final result = await _methodChannel.invokeMethod<bool>('requestBluetoothPermission'); final result =
await _methodChannel.invokeMethod<bool>('requestBluetoothPermission');
return result ?? false; return result ?? false;
} catch (e) { } catch (e) {
print('请求蓝牙权限失败: $e'); print('请求蓝牙权限失败: $e');

Loading…
Cancel
Save