-
如果你刚要开始做一个连接蓝牙设备的App,你就看到了这篇文章,恭喜你,节省了至少一天的时间。
-
如果你遇到了IOS和安卓连接蓝牙设备不一样的问题,恭喜你找对地方了。
-
本文阐述了一下ios和安卓连接蓝牙遇到的问题,主要是设备id的获取方式的问题。其他问题请绕路。
-
坑:安卓设备获取蓝牙设备的device id,得到的是一个mac地址,通过蓝牙扫描协议可以查看到的。而IOS为了安全起见,隐藏了蓝牙设备的mac地址,device id返回了一个uuid,并且不同的扫描批次,拿到的uuid是不一致的。
-
deviceId,天生就具有迷惑性,我们理所当然的看到他,就认为这是设备的唯一ID,无论安卓还是IOS都是一样的,这就错了。ios的deviceid,只是这次扫描到了比如100个蓝牙设备,用来区分这100个设备的。你可以通过他指定我要连接哪一个,但是无法在系统中用作唯一连接标识符。
-
这是不合理的,尤其是在工业上,比如我用三个蓝牙测振仪,放在一台机器的三个部位上。如果要进行连接,你扫描到的是完全一模一样的三个设备。UUID又是变化的,我tm怎么区分哪个是哪个?
-
当然,可以使用rssi来进行判断。我通过实验发现,当手机贴近蓝牙设备时,就是紧紧贴在一起,rssi一般可以达到-30甚至更大(-20),稍远一点的距离,rssi一般是达到60-100。我们可以根据实际手机贴近蓝牙设备时,rssi变化最趋近实际情况的那个设备,来判定是否是我们要连接的设备。
-
这是一个相对靠谱,但是需要连接时进行移动操作(贴近蓝牙设备)的,如果实际情况不允许这么干,那就无法做到(比如蓝牙设备在玻璃盒子里,或者距离较远)。
-
回头仔细观察扫描结果,发现有一个advertisementData字段,查看相关资料,发现这里边存放有一些厂商的特别信息。
-
比如我连接的测振仪,就把mac地址,以byte数组的格式放到 r.advertisementData?.manufacturerData里边了。这是一个map,key有点没看懂,直接用values就可以了。(解完发现这个byte数组转成16进制字符串,用:分隔开,比安卓获取的deviceId多几位)具体干啥的不清楚,但是完整的mac地址是包含在内的。
-
这个办法行,但是也有点问题,有些设备,根本就没有manufactureData字段,或者内容是空的。那就不行了,只能通过rssi的变化趋势去判定哪个设备是哪一个了。因为根据列表选择,你也无法判断一大堆名字都叫nxf54的设备哪个对应实际的哪一个。
-
上代码
if (Platform.isAndroid) {
device = scanResults.firstWhere((r) {
return item?.deviceCheckItem?.checkConfig?.seismic?.sn == r.device.id?.toString();
}, orElse: () {
return ScanResult();
})?.device;
} else {
scanResults.sort((a, b) => b.rssi - a.rssi);
for (var r in scanResults) {
debugPrint(r.rssi.toString());
if (r.advertisementData?.manufacturerData?.values?.isEmpty ?? false) {
continue;
}
var listInt = r.advertisementData?.manufacturerData?.values?.first ?? <int>[];
var address = "";
for (var x in listInt) {
var hex = '${x.toRadixString(16)}'.padLeft(2, '0');
address = "${address.isEmpty ? '' : '$address:'}$hex";
}
address = address.toLowerCase();
if (address.endsWith(item?.deviceCheckItem?.checkConfig?.seismic?.sn?.toLowerCase() ?? '===')) {
device = r.device;
debugPrint("IOS 连接到精确设备:${device.name}(${device.id})");
break;
}
}
// 要是还是找不到,就按照最近的一个蓝牙设备,名称是nRF52连接即可。
if (device == null) {
for (var r in scanResults) {
if (r.rssi >= -40 && r.device.name.isNotEmpty && r.device.name == 'nRF52') {
device = r.device;
debugPrint("IOS 连接到最近的一个设备:${device.name}(${device.id})");
break;
}
}
}
// IOS
}
评论区