iOS 藍牙交互的坑

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,和兩個藍牙設備,一開始是這樣的

1.png

A連接上了,并且用第一個CBCentralManger可以發送數據給它,B沒有連接上。這時候,我就需要第二個CBCentralManager重新掃描附近的設備(包括手機已經連接上的設備,包括A)來連接B

2.png

在這個過程中,第二個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];
    }
}

最后幫朋友打個小廣告

一個有趣的迷你小程序

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 首先進一則廣告: 藍牙技術聯盟(Bluetooth SIG)2010年7月7日宣布,正式采納藍牙4.0核心規范(B...
    L澤閱讀 1,473評論 3 4
  • 本文主要以藍牙4.0做介紹,因為現在iOS能用的藍牙也就是只僅僅4.0的設備 用的庫就是core bluetoot...
    暮雨飛煙閱讀 857評論 0 2
  • 這里我們具體說明一下中心模式的應用場景。主設備(手機去掃描連接外設,發現外設服務和屬性,操作服務和屬性的應用。一般...
    丶逝水流年閱讀 2,289評論 3 4
  • iOS開發藍牙4.0初識轉載 2015-09-20 15:26:44標簽:ios開發藍牙ios開發藍牙4.0ios...
    Jany_4a9a閱讀 2,768評論 0 3
  • 淺賦紅霞賞畫情,清吟淡露竹思生。 琴音步韻聽閑趣,試作新詞待友評。
    sujing123閱讀 158評論 0 4