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];
}
}
最后幫朋友打個小廣告