歡迎訪問(wèn)我的博客 muhlenXi,該文章出自我的博客,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明來(lái)源: http://muhlenxi.com/2017/05/03/iOS-Bluetooth-Low-Energy-Develop-Chapter4。
導(dǎo)語(yǔ):
在這一節(jié),主要是 iOS APP 關(guān)于藍(lán)牙后臺(tái)處理方面的知識(shí)和經(jīng)驗(yàn)。
對(duì)于 iOS APP 來(lái)說(shuō),知道你的 APP 是運(yùn)行在前臺(tái)還是運(yùn)行在后臺(tái)很重要。一個(gè) APP 在后臺(tái)運(yùn)行狀態(tài)下的行為表現(xiàn)必須不同于前臺(tái),因?yàn)?iOS 設(shè)備的系統(tǒng)資源是有限的。關(guān)于 iOS 后臺(tái)運(yùn)行處理的更多論述 請(qǐng)查閱 Background Execution.
默認(rèn)情況下,當(dāng)你的 APP 在 background(后臺(tái)運(yùn)行)或者處于 suspended state(暫停狀態(tài))時(shí),無(wú)論是 Central 端還是 Peripheral 端,許多常見(jiàn)的 CoreBluetooth 任務(wù)是不能被執(zhí)行的。也就是說(shuō),你可以聲明你的 APP 支持 CoreBluetooth 后臺(tái)運(yùn)行模式來(lái)允許你的 APP 進(jìn)入 suspended state 后依然能夠喚醒來(lái)處理一些藍(lán)牙的事件。即使你的 APP 不需要全面的后臺(tái)處理支持,但是當(dāng)有重要事件發(fā)生的時(shí)候也需要系統(tǒng)給你發(fā)出彈框提醒。
即使你的 APP 不管支持哪一個(gè) CoreBluetooth 后臺(tái)運(yùn)行模式,它也不能一直在后臺(tái)運(yùn)行。在某個(gè)時(shí)刻,系統(tǒng)會(huì)終止你的 APP 來(lái)為處于前臺(tái)的其他 APP 提供內(nèi)存空間,從而導(dǎo)致一些活動(dòng)或者連接丟失。比如,對(duì)于 iOS 7, CoreBluetooth 支持 Central Manager 和 Peripheral Manager 對(duì)象狀態(tài)信息的保存和在 APP 啟動(dòng)時(shí)恢復(fù)該狀態(tài)信息,你可以使用這個(gè)功能來(lái)支持藍(lán)牙設(shè)備的長(zhǎng)期操作。
只能前臺(tái)運(yùn)行的 APP
除非你請(qǐng)求允許執(zhí)行特定的后臺(tái)任務(wù),否則對(duì)于大多數(shù) iOS APP 來(lái)說(shuō),當(dāng)你的 APP 進(jìn)入 background state(后臺(tái)狀態(tài))不久后就會(huì)處于 suspended state(暫停狀態(tài))。當(dāng)你的 APP 處于 suspended state 時(shí)是不能執(zhí)行藍(lán)牙相關(guān)的任務(wù),也不能感知到任何藍(lán)牙事件直到重新進(jìn)入 foreground(前臺(tái))。
在 Central 端,沒(méi)有聲明支持 CoreBluetooth 后臺(tái)運(yùn)行模式的 APP,也就是只能前臺(tái)運(yùn)行的 APP,在 background 和 suspended 狀態(tài)時(shí),是不能搜索正在廣播數(shù)據(jù)的 Peripheral。在 Peripheral 端,則是不能進(jìn)行廣播數(shù)據(jù)。此時(shí)如果一個(gè) Central 嘗試獲取 Peripheral Characteristic 的值會(huì)收到一個(gè)錯(cuò)誤。
根據(jù)使用情況,這種默認(rèn)行為可能會(huì)以多種方式影響你的 APP,舉個(gè)例子,試想一下,當(dāng)你正在與剛連接的 Peripheral 進(jìn)行數(shù)據(jù)交互時(shí),此時(shí)你的 APP 進(jìn)入 suspended 狀態(tài)(當(dāng)用戶切換到另一個(gè) APP時(shí))中,如果 Peripheral 此時(shí)失去連接,你是不能感知到已經(jīng)發(fā)生 disconnection(斷開(kāi)連接)事件了,直到你的 APP 重新進(jìn)入 foreground 為止。
使用 Peripheral Connection options(選項(xiàng))
只在前臺(tái)運(yùn)行的 APP 處于 suspended 狀態(tài)時(shí),系統(tǒng)會(huì)將發(fā)生的所有藍(lán)牙事件加入隊(duì)列,只有當(dāng) APP 重新進(jìn)入前臺(tái)時(shí),才會(huì)將事件傳遞給 APP,也就是說(shuō),當(dāng) Central 產(chǎn)生事件時(shí),CoreBluetooth 通過(guò)彈框提醒的方式通知用戶。用戶可以通過(guò)這個(gè)提醒來(lái)決定是否將 APP 重新打開(kāi)來(lái)處理這個(gè)特定事件。
當(dāng)調(diào)用 CBCentralManager 類的 connectPeripheral:options: 方法連接 Remote Peripheral 時(shí),你可以利用下面這些 Peripheral 連接選項(xiàng)來(lái)設(shè)置彈框提醒。
-
CBConnectPeripheralOptionNotifyOnConnectionKey-- 如果建立了一個(gè)成功的連接,此時(shí) APP 進(jìn)入 suspended 狀態(tài)時(shí),如果你想要系統(tǒng)為給定 Peripheral 顯示一個(gè)彈框,你可以在 options 選項(xiàng)中包含這個(gè)鍵。 -
CBConnectPeripheralOptionNotifyOnDisconnectionKey-- 如果發(fā)生了 disconnection 事件,此時(shí) APP 進(jìn)入 suspended 狀態(tài)時(shí),如果你想要系統(tǒng)為給定 Peripheral 顯示一個(gè)彈框,你可以在 options 選項(xiàng)中包含這個(gè)鍵。 -
CBConnectPeripheralOptionNotifyOnNotificationKey-- 如果收到了 Peripheral 的通知,此時(shí) APP 進(jìn)入 suspended 狀態(tài)時(shí),如果你想要系統(tǒng)顯示一個(gè)來(lái)自 Peripheral 的通知彈框,你可以在 options 選項(xiàng)中包含這個(gè)件。
關(guān)于 Peripheral 連接參數(shù)的更多信息可以查閱 Peripheral Connection Options 常量。
CoreBluetooth 后臺(tái)運(yùn)行模式
如果你的 APP 在后臺(tái)運(yùn)行狀態(tài)下也需要執(zhí)行藍(lán)牙任務(wù),你必須在 Info.plist (Infomation property list) 文件中聲明你的 APP 支持 CoreBluetooth 后臺(tái)運(yùn)行模式。當(dāng)你聲明后,系統(tǒng)會(huì)喚醒 suspended 狀態(tài)中的 APP 來(lái)處理藍(lán)牙事件。這對(duì)于和每隔一段時(shí)間就傳遞數(shù)據(jù)的 BLE 設(shè)備進(jìn)行交互的 APP 來(lái)說(shuō)很重要,比如一個(gè)心率監(jiān)測(cè)器。
APP 可能會(huì)聲明的 CoreBluetooth 后臺(tái)運(yùn)行模式有兩種。一種是 APP 扮演了 Central 的角色,另一種則是 APP 扮演了 Peripheral 的角色。如果你的 APP 同時(shí)扮演了這兩種角色,你可以同時(shí)聲明這兩種后臺(tái)運(yùn)行模式。聲明 CoreBluetooth 后臺(tái)運(yùn)行模式的方式就是在 Info.plist 文件中加入一個(gè) UIBackgroundModes 的 Key,Value 則是包含以下提到的兩種字符串的數(shù)組:
-
bluetooth-central-- APP 使用 CoreBluetooth 框架與其他 BLE 設(shè)備進(jìn)行通信。 -
bluetooth-peripheral-- APP 使用 CoreBluetooth 框架來(lái)分享數(shù)據(jù)。
提示:Xcode 的屬性列表編輯器默認(rèn)顯示的 Key 是人類易讀的字符,而不是實(shí)際的 Key 的名字,要在 Info.plist 文件中顯示實(shí)際 Key 名,按住 Control鍵并單擊編輯器窗口中的任意 Key,并在彈出的上下文窗口中啟用 Show Raw Keys/Values 項(xiàng)。比如 UIBackgroundModes 的易讀 Key 名則是 Required background modes,如圖所示

關(guān)于如何配置 Info.plist 文件內(nèi)容的更多信息請(qǐng)查閱 Xcode help
bluetooth-central 后臺(tái)運(yùn)行模式
當(dāng)扮演一個(gè) Central 角色的 APP 在 Info.plist 文件中包含了 UIBackgroundModes bluetooth-central 鍵值對(duì)時(shí),CoreBluetooth 框架允許你的 APP 在后臺(tái)運(yùn)行時(shí)執(zhí)行藍(lán)牙任務(wù)。當(dāng)你的 APP 在后臺(tái)運(yùn)行時(shí),你仍舊可以搜索和連接 Peripheral,然后與之進(jìn)行數(shù)據(jù)交互。此外,當(dāng) CBCentralManagerDelegate 或者 CBPeripheralDelegate 的代理方法進(jìn)行回調(diào)時(shí),系統(tǒng)會(huì)喚醒你的 APP 允許你來(lái)處理這些 Central 端的重要事件。比如,成功建立了連接,連接中斷,Peripheral 發(fā)送了一個(gè)更新值的通知,或者 Central Manager 的狀態(tài)發(fā)生改變。
盡管你的 APP 在后臺(tái)運(yùn)行時(shí)可以執(zhí)行許多藍(lán)牙任務(wù),但是你要注意這些,在后臺(tái)運(yùn)行狀態(tài)下,當(dāng)你搜索 Peripheral 的操作是不同于前臺(tái)運(yùn)行狀態(tài)的。特別是當(dāng)你 APP 在后臺(tái)運(yùn)行狀態(tài)下搜索設(shè)備:
- 搜索參數(shù)
CBCentralManagerScanOptionAllowDuplicatesKey將會(huì)被忽略,多個(gè)廣播數(shù)據(jù)的 Peripheral 發(fā)現(xiàn)事件將合并成一個(gè)發(fā)現(xiàn)事件。 - 如果所有的都在后臺(tái)運(yùn)行中搜索 Peripheral,則 Central 搜索廣播數(shù)據(jù)包的時(shí)間間隔將會(huì)增加,你發(fā)現(xiàn)一個(gè)廣播數(shù)據(jù)的 Peripheral 將會(huì)需要很長(zhǎng)時(shí)間。
這種策略對(duì)降低 Radio 的使用頻率和提高 iOS 設(shè)備的續(xù)航時(shí)間有幫助。
bluetooth-peripheral 后臺(tái)運(yùn)行模式
Peripheral 想要在后臺(tái)執(zhí)行藍(lán)牙任務(wù),你必須在 Info.plist 文件中包含了 UIBackgroundModes bluetooth-peripheral 鍵值對(duì),這樣系統(tǒng)會(huì)喚醒你的 APP 來(lái)處理讀、寫(xiě)和訂閱事件。
除了允許你的 APP 喚醒來(lái)處理讀、寫(xiě)和來(lái)自 Central 的訂閱請(qǐng)求外,CoreBluetooth 框架還允許你的 APP 在后臺(tái)運(yùn)行狀態(tài)下廣播數(shù)據(jù)。也就是說(shuō),你應(yīng)該注意到,在后臺(tái)狀態(tài)下廣播數(shù)據(jù)與在前臺(tái)狀態(tài)下的操作是不同的。特別是后臺(tái)狀態(tài)下廣播數(shù)據(jù):
- 廣播的
CBAdvertisementDataLocalNameKeyKey 將被忽略,Peripheral 的 local name 也不會(huì)廣播。 - 廣播中 CBAdvertisementDataServiceUUIDsKey 的值的所有服務(wù) UUID 都被放置在 “overflow” 區(qū)域中。只有當(dāng) iOS 設(shè)備進(jìn)行顯式搜索才會(huì)被發(fā)現(xiàn)。
- 如果所有 APP 都在后臺(tái)運(yùn)行狀態(tài)下廣播數(shù)據(jù),你的 Peripheral 廣播數(shù)據(jù)包的頻率將會(huì)降低。
謹(jǐn)慎使用后臺(tái)運(yùn)行模式
對(duì)于一般用戶情況,可能不需要聲明 APP 支持其中一個(gè)或兩個(gè) CoreBluetooth 后臺(tái)運(yùn)行模式,你應(yīng)該對(duì)后臺(tái)進(jìn)程負(fù)責(zé),因?yàn)閳?zhí)行藍(lán)牙的任務(wù)需要使用用戶設(shè)備的 onboard radio(板載廣播),使用廣播會(huì)影響用戶設(shè)備的續(xù)航時(shí)間,應(yīng)盡量減少在后臺(tái)執(zhí)行藍(lán)牙任務(wù)。APP 被藍(lán)牙時(shí)間喚醒后應(yīng)迅速處理該事件然后盡可能快速的進(jìn)入 suspended 狀態(tài)。
聲明支持 CoreBluetooth 后臺(tái)運(yùn)行模式的 APP 必須遵守一些基本準(zhǔn)則:
- APP 應(yīng)該提供一個(gè)基于會(huì)話的界面來(lái)允許用戶決定什么時(shí)候開(kāi)始和結(jié)束發(fā)送藍(lán)牙事件。
- 一個(gè) APP 被喚醒時(shí)有 10秒 來(lái)完成一個(gè)任務(wù),理想地,APP 應(yīng)該盡快的完成任務(wù)然后再次進(jìn)入 suspended 狀態(tài)。APP 在后臺(tái)運(yùn)行時(shí)間太長(zhǎng)會(huì)被系統(tǒng)限制或殺死。
- APP 不應(yīng)該一直處于喚醒狀態(tài)來(lái)處理與系統(tǒng)喚醒無(wú)關(guān)的額外任務(wù)。
在后臺(tái)運(yùn)行狀態(tài)下,你的 APP 應(yīng)該如何操作的詳情請(qǐng)查閱 Being a Responsible Background App.
在后臺(tái)執(zhí)行長(zhǎng)期操作
一些 APP 可能需要使用 CoreBluetooth 框架來(lái)在后臺(tái)運(yùn)行狀態(tài)下執(zhí)行長(zhǎng)期操作,比如,你想要為 iOS 設(shè)備開(kāi)發(fā)一個(gè) 安全家庭 APP 來(lái)與配備 BLE 技術(shù)的門(mén)鎖進(jìn)行通信。APP 與門(mén)鎖交互來(lái)自動(dòng)鎖門(mén)(當(dāng)用戶離開(kāi)家的時(shí)候)和開(kāi)鎖(當(dāng)用戶回家的時(shí)候),整個(gè)期間 APP 一直在后臺(tái)運(yùn)行狀態(tài)下。當(dāng)用戶離家的時(shí)候,iOS 設(shè)備終會(huì)超出門(mén)鎖的有效范圍,導(dǎo)致與門(mén)鎖的連接中斷。在這種情況下,APP 可以通過(guò)調(diào)用 CBCentralManager 類的 connectPeripheral:options:該方法來(lái)建立連接,因?yàn)檫B接請(qǐng)求不會(huì)超時(shí),這樣當(dāng)用戶到家的時(shí)候就會(huì)與門(mén)鎖重新連接。
現(xiàn)在試想一種情況,當(dāng)用戶離家有一些天了,如果此時(shí) APP 被系統(tǒng)給終止了。這樣當(dāng)用戶回家的時(shí)候,APP 將不能與門(mén)鎖重新連接,用戶也不能打開(kāi)門(mén)鎖了。類似這樣的 APP,使用 CoreBluetooth 來(lái)執(zhí)行長(zhǎng)期操作至關(guān)重要,例如監(jiān)視活動(dòng)和掛起連接。
狀態(tài)保存和恢復(fù)
因?yàn)闋顟B(tài)保存和恢復(fù)已經(jīng)內(nèi)置于 CoreBluetooth,你的 APP 可以選擇加入這個(gè)功能來(lái)要求系統(tǒng)保存 APP 的 Central Manager 和 Peripheral Manager 的狀態(tài),并繼續(xù)代表他們執(zhí)行藍(lán)牙任務(wù),即使你的 APP 不在運(yùn)行,當(dāng)這些任務(wù)完成后,系統(tǒng)會(huì)重新讓你的 APP 進(jìn)入后臺(tái)運(yùn)行狀態(tài)并給予一定的時(shí)間來(lái)保存狀態(tài)和處理一些藍(lán)牙事件。對(duì)于上述描述的安全家庭 APP 這種情況來(lái)說(shuō),系統(tǒng)將會(huì)監(jiān)聽(tīng)連接請(qǐng)求,當(dāng)用戶回家的時(shí)候,系統(tǒng)將會(huì)重新啟動(dòng) APP 來(lái)處理 centralManager:didConnectPeripheral: 代理回調(diào)和完成連接請(qǐng)求。
CoreBluetooth 對(duì) 扮演 Central 角色,Peripheral 角色,或者同時(shí)都扮演的 APP 都提供狀態(tài)保存和恢復(fù)支持。當(dāng)扮演 Central 角色的 APP 增加狀態(tài)保存和恢復(fù)時(shí),當(dāng)系統(tǒng)釋放內(nèi)存空間需要終止你的 APP 時(shí),會(huì)保存你的 Central Manager 的狀態(tài),如果你的 APP 擁有多個(gè) Central Manager,你可以選擇你想要系統(tǒng)跟蹤的 Central Manager,尤其,對(duì)于給定的 CBCentralManager 對(duì)象,系統(tǒng)會(huì)跟蹤:
- Central Manger 搜索的 Service(和一些一開(kāi)始指定搜索參數(shù)選項(xiàng)的)
- Central Manager 嘗試連接或者已經(jīng)連接的 Peripheral
- Central Manager 訂閱的 Characteristic
扮演 Peripheral 角色的 APP 同樣可以使用狀態(tài)保存與恢復(fù)。對(duì)于 CBPeripheralManager 對(duì)象,系統(tǒng)會(huì)跟蹤:
- Peripheral Manager 廣播的數(shù)據(jù)
- Peripheral Manager 發(fā)布到設(shè)備庫(kù)中的 Services 和 Characteristics
- 被 Central 訂閱的 Characteristic 的值
當(dāng)你的 APP 被系統(tǒng)置入后臺(tái)運(yùn)行狀態(tài)時(shí),你可以重新實(shí)例化 APP 的 Central Manager 和 Peripheral Manager 并恢復(fù)他們的狀態(tài)。下面的章節(jié)會(huì)詳細(xì)的描述如何在你的 APP 中使用狀態(tài)保存和恢復(fù)。
添加狀態(tài)保存和恢復(fù)支持
CoreBluetooth 的狀態(tài)保存和恢復(fù)是選擇性加入的功能,需要以下步驟來(lái)讓 APP 這一功能生效,你可以參考一下的步驟來(lái)給你的 APP 增加狀態(tài)保存和恢復(fù)功能:
- 1、(必須的)當(dāng)你 allocate 和 initialize 一個(gè) Central Manager 或 Peripheral Manager 對(duì)象時(shí)需要加入狀態(tài)保存和恢復(fù)。這一步在
選擇加入狀態(tài)與恢復(fù)小節(jié)有詳細(xì)描述。 - 2、(必須的)當(dāng)系統(tǒng)啟動(dòng) APP 的時(shí)候需要重新實(shí)例化一些 Central Manager 或 Peripheral Manager 對(duì)象。這一步在
重新實(shí)例化你的 Central Manager 和 Peripheral Manager小節(jié)有詳細(xì)描述。 - 3、(必須的) 實(shí)現(xiàn)恰當(dāng)?shù)拇矸椒?。這一步在
實(shí)現(xiàn)恰當(dāng)?shù)?Restoration Delegate 方法小節(jié)有詳細(xì)描述。 - 4、(可選的)更新你的 Central Manager 或 Peripheral Manager 的初始化進(jìn)程。這一步在
更新你的初始化進(jìn)程小節(jié)中有詳細(xì)描述。
選擇加入狀態(tài)保存與恢復(fù)
選擇加入狀態(tài)保存和恢復(fù)功能后,當(dāng)你 allocate 和 initialize 一個(gè) Central Manager 或者 Peripheral Manager 的時(shí)候,你需要提供一個(gè)唯一的恢復(fù)標(biāo)識(shí)符?;謴?fù)標(biāo)識(shí)符是一個(gè)標(biāo)識(shí) Central Manager 或者 Peripheral Manager 的字符串,字符串的值對(duì)你的代碼很重要,它將會(huì)告訴 CoreBluetooth 需要保存使用該標(biāo)記的對(duì)象,CoreBluetooth 只保存這些擁有恢復(fù)標(biāo)識(shí)符的對(duì)象。
舉個(gè)例子,為你的 APP (只有一個(gè) CBCentralManager 對(duì)象的 Central )選擇加入狀態(tài)保存和恢復(fù),當(dāng)你初始化 Central Manager 的時(shí)候需要指定 options(初始化選項(xiàng)),選項(xiàng)是一個(gè)以 CBCentralManagerOptionRestoreIdentifierKey 為 key,Value 是 恢復(fù)標(biāo)識(shí)符 的字典。示例代碼如下:
myCentralManager =
[[CBCentralManager alloc] initWithDelegate:self queue:nil
options:@{ CBCentralManagerOptionRestoreIdentifierKey:
@"myCentralManagerIdentifier" }];
雖然上述例子沒(méi)有證明這一點(diǎn),當(dāng)你給使用 Peripheral Manager 對(duì)象的 APP 選擇加入狀態(tài)保存與恢復(fù)時(shí)應(yīng)使用類似的方式:在你初始化 Peripheral Manager 的時(shí)候指定 options(初始化選項(xiàng)),選項(xiàng)是一個(gè)以 CBCentralManagerOptionRestoreIdentifierKey 為 key,Value 是 恢復(fù)標(biāo)識(shí)符 的字典。
提示:因?yàn)橐粋€(gè) APP 可能擁有多個(gè) CBCentralManager 和 CBPeripheralManager 對(duì)象的實(shí)例,你應(yīng)該確保他們的恢復(fù)標(biāo)識(shí)符是唯一的,這樣系統(tǒng)就能正確地區(qū)分它們。
重新實(shí)例化你的 Central Manager 和 Peripheral Manager
當(dāng)你的 APP 被系統(tǒng)從后臺(tái)啟動(dòng)時(shí),你需要做的第一件事就是用狀態(tài)恢復(fù)標(biāo)識(shí)符重新實(shí)例化合適的 Central Manager 和 Peripheral Manager,恢復(fù)標(biāo)識(shí)符要跟它們第一次被創(chuàng)建的一樣。如果你的 APP 僅僅用到了一個(gè) Central Manager 或者 Peripheral Manager,并且該 Manager 在你的 APP 生命周期中還存活著,則你就不需要做這一步。
如果你的 APP 使用超過(guò)一個(gè)以上的 Central Manager 或者 Peripheral Manager,或者使用的 Manager 在 APP 的生命周期中已經(jīng)死亡了。當(dāng)你的 APP 被系統(tǒng)啟動(dòng)時(shí),它需要知道要恢復(fù)哪一個(gè) Manager 。你可以通過(guò) APP 終止時(shí)保存的 Manager 對(duì)象的恢復(fù)標(biāo)識(shí)符列表,使用合適的 launch option(啟動(dòng)選項(xiàng))參數(shù)(UIApplicationLaunchOptionsBluetoothCentralsKey 或者 UIApplicationLaunchOptionsBluetoothPeripheralsKey)在 application:didFinishLaunchingWithOptions: 代理方法回調(diào)中來(lái)獲取恢復(fù)標(biāo)識(shí)符數(shù)組。
舉個(gè)例子,當(dāng)系統(tǒng)啟動(dòng) APP 時(shí),你可以恢復(fù)所有 Central Manager 的恢復(fù)標(biāo)識(shí)符,示例代碼如下:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSArray *centralManagerIdentifiers =
launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
// ...
}
當(dāng)你獲得恢復(fù)標(biāo)識(shí)符列表后,遍歷這個(gè)數(shù)組來(lái)重新實(shí)例化合適的 Central Manager 對(duì)象。
提示:當(dāng) APP 啟動(dòng)時(shí),系統(tǒng)只會(huì)提供要執(zhí)行一些藍(lán)牙任務(wù)(此時(shí) APP 沒(méi)有在運(yùn)行)的 Central Manager 和 Peripheral Manager 的恢復(fù)標(biāo)識(shí)符。關(guān)于啟動(dòng)選項(xiàng)參數(shù) Keys 的詳情可以參考 UIApplicationDelegate Protocol Reference.
.
實(shí)現(xiàn)恰當(dāng)?shù)?Restoration Delegate 方法
當(dāng)你恢復(fù)合適的 Central Manager 和 Peripheral Manager 后,然后將他們的狀態(tài)與藍(lán)牙系統(tǒng)的狀態(tài)同步。為了使你的 APP 達(dá)到系統(tǒng)處理的速度,你必須實(shí)現(xiàn)恰當(dāng)?shù)?Restoration Delegate 方法,對(duì) Central Manager ,需要實(shí)現(xiàn) centralManager:willRestoreState: 代理方法,而對(duì)于 Peripheral Manager,則需要實(shí)現(xiàn) peripheralManager:willRestoreState: 代理方法。
重要提示:對(duì)于選擇添加 CoreBluetooth 的狀態(tài)保存與恢復(fù)的 APP,當(dāng) APP 從后臺(tái)啟動(dòng)來(lái)完成一些藍(lán)牙任務(wù)時(shí),會(huì)第一個(gè)調(diào)用 centralManager:willRestoreState: 和 peripheralManager:willRestoreState: 代理方法,對(duì)于沒(méi)有加入狀態(tài)與恢復(fù)的 APP,會(huì)第一個(gè)調(diào)用 centralManagerDidUpdateState: 和 peripheralManagerDidUpdateState: 代理方法。
以上提到的這些代理方法,最后一個(gè)參數(shù)是一個(gè)字典,該字典包含 APP 終止時(shí)系統(tǒng)保存的 Manager 的信息。字典中可用的 Keys,可以查閱 Central Manager State Restoration Options 和 Peripheral_Manager_State_Restoration_Options 常量。
用 centralManager:willRestoreState: 代理方法提供的字典的 Key 來(lái)恢復(fù) CBCentralManager 對(duì)象的狀態(tài)。舉個(gè)例子,如果你的 Central Manager 擁有激活的或者中斷的連接(APP 終止時(shí)),系統(tǒng)會(huì)繼續(xù)監(jiān)視 APP 的行為,如下所示,你可以通過(guò) CBCentralManagerRestoredStatePeripheralsKey Key 去得到 Central Manager 連接的或者嘗試連接的 Peripheral 列表(用 CBPeripheral 對(duì)象表示)。
- (void)centralManager:(CBCentralManager *)central
willRestoreState:(NSDictionary *)state {
NSArray *peripherals =
state[CBCentralManagerRestoredStatePeripheralsKey];
// ...
}
當(dāng)你獲得 Peripheral 列表后然后干什么取決于使用情況。舉個(gè)例子,如果 APP 有一個(gè) Central Manager 搜索的 Peripheral 列表,你可能想把恢復(fù)的 Peripheral 加入該列表中。此時(shí)確保要設(shè)置 Peripheral 的 Delegate 以保證能收到合適的代理回調(diào)。
你可以通過(guò)類似的方法利用 peripheralManager:willRestoreState: 代理方法提供的字典的 keys 來(lái)恢復(fù) CBPeripheralManager 的狀態(tài)。
更新你的初始化進(jìn)程
當(dāng)你實(shí)現(xiàn)前面必須的步驟后,你可能想要查看 Central Manager 和 Peripheral Manager 的初始化進(jìn)程。盡管這是一個(gè)可選的步驟,但對(duì)確保 APP 穩(wěn)定運(yùn)行很重要。舉個(gè)例子,當(dāng)正與連接的 Peripheral 數(shù)據(jù)傳輸?shù)揭话霑r(shí),APP 終止了。當(dāng)你的 APP 恢復(fù)這個(gè) Peripheral 時(shí),你不知道 APP 終止時(shí)數(shù)據(jù)處理到哪一步,你想要確定從哪里繼續(xù)開(kāi)始處理。
舉個(gè)例子,當(dāng)在 centralManagerDidUpdateState: 代理方法中初始化 APP 時(shí),如果你能夠成功的從一個(gè)恢復(fù)的 Peripheral中找出指定的 Service(在 APP 終止之前),就像這樣
NSUInteger serviceUUIDIndex =
[peripheral.services indexOfObjectPassingTest:^BOOL(CBService *obj,
NSUInteger index, BOOL *stop) {
return [obj.UUID isEqual:myServiceUUIDString];
}];
if (serviceUUIDIndex == NSNotFound) {
[peripheral discoverServices:@[myServiceUUIDString]];
// ...
}
以上示例中,如果系統(tǒng)在你調(diào)用 discoverServices: 方法完成 Servic 搜索之前終止。如果 APP 搜索 Service 成功,你可以稍后查看是否發(fā)現(xiàn)合適的 Characteristic(一直訂閱的) ,用這種方式來(lái)更新初始化進(jìn)程,你需要在正確的時(shí)間調(diào)用正確的方法。
參考文獻(xiàn)
1、Core Bluetooth Background Processing for iOS Apps
結(jié)束語(yǔ)
歡迎在本文下面留言一起交流心得...