1.获取mac地址的问题
刚开始做蓝牙开发的时候,翻遍了Apple的文档和各个论坛,希望能找到不需要连接蓝牙设备就能获取mac地址的方法,结果都是无功而返,最后只能通过读取特征值"2A23"来获取。 然而,android是可以不需要连接就可以获取到蓝牙设备的mac地址的(貌似是在广播包里面的吧)。不管Apple是出于安全还是什么原因的考量,这个机制真的好麻烦。
当然,如果是自己内部使用的App,或者是用在越狱设备上的App,可以尝试使用liblockdown.dylib来解决。
2.给蓝牙设备发送数据失败
App中需要同时连接多个CBPeripheral, 发送指令可以使蓝牙设备报警。刚开始测试的时候偶尔情况下,发送指令之后,蓝牙设备没有反应(之后也不会有反应),然而,CBPeripheral.state却变成disconnected了,奇怪的是蓝牙断连的回调方法并没有调用。
后来,由于功能剧增,代码量也暴涨,只好把蓝牙模块独立出来。之前是用一个CBCentralManager实例同时连接多个CBPeripheral。这次就用一个CBCentralManger连接一个CBPeripheral。结果,改造完之后,就经常出现发送数据失败的问题。
一直懵逼,直到看到这里:
NSArray *connectedDevices = [self.centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:@"180F"]]];
for (CBPeripheral *peripheral in connectedDevices) {
[self.centralManager connectPeripheral:peripheral options:nil];
}
这段代码的用途是为了获取手机上已经连接的蓝牙设备。问题就出现在这里。比如:我有两个蓝牙设备A,B, A已经连接上,并且发送数据正常;B没有连接上,所以,我需要刷新,重新扫描附近的设备来连接B。 等B扫描完之后,再给A发送数据,发现蓝牙设备A没有响应了。
原理是这样的:我同时有两个CBCentralManager,和两个蓝牙设备,一开始是这样的
A连接上了,并且用第一个CBCentralManger可以发送数据给它,B没有连接上。这时候,我就需要第二个CBCentralManager重新扫描附近的设备(包括手机已经连接上的设备,包括A)来连接B
在这个过程中,第二个CBCentralManager会连接上A(因为A是手机已经连接上的设备,我需要连接上A,然后读取"2A23"特征值来获取它的mac地址,然后判断它是不是B),导致A和第一个CBCentralManager之间的连接断开(CBPeripheral.state 变为disconnected).从而导致第一个CBCentralManager给A发送数据永远不会成功了。(坑的是,即使CBPeripheral.state已经变为disconnected了,蓝牙的断开连接回调方法并没有调用)
即
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
在这种情况下是不会调用的。其实这时候该peripheral和这个centralManager之间的连接已经断开了。所以后续的通过peripheral给character写数据是不会成功的。(补:像上面的情况貌似是硬件的问题,原则上来说连接上之后就不应该再发广播包了,别的centralManager也不会再发现该设备,由于硬件工程师已经不在了,也无法验证这个问题。)
3.蓝牙后台扫描
即使在info.plist文件里面设置了App communicates using CoreBluetooth,但是app一退到后台,蓝牙扫描就扛不住了,不干活了,后来搜一些资料,像下面的设置证明是可行的:
[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"180D"]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)}];// 扫描外围设备,可以指定含有指定服务的外围设备
在扫描的时候指定你要扫描的设备提供的service即可,当然,这里不能乱设置,需要指定那些在广播包里面提供的service才行。
有哪些service可以到下面的代理方法里面打印一下advertisementData即可。
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
}
4.[ERROR] XPC connection interrupted, resetting
如果连接的蓝牙设备数量太多会导致[ERROR] XPC connection interrupted, resetting,centralManager也会挂掉。解决方法就是在发现设备的时候有限制的去连接,比如超过8台就不搭理它就可以了。
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
if (self.nDevices.count > 8) {
return;
}
if (![self.nDevices containsObject:peripheral]) {
[self.nDevices addObject:peripheral];
[self.manager connectPeripheral:peripheral options:nil];
}
}
最后帮朋友打个小广告