蘋果藍牙后台的限制,原本廣播會有兩個段分別是localName和serviceUUID這兩塊,但現在后台廣播時,是不發送在這兩段的
手機app可以作為一個藍牙外設端來模擬外設硬件,但廣播包里的數據只能包含localName和serviceUUID,相對於外設硬件來說還是有一些不足之處。
一個128位的藍牙UUID來標示
32個 x 是 0-9 或 a-f 范圍內的一個十六進制的數字(0x00),X是字符串格式
把數據按uuid的格式加進去
self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:serviceUUIDs,CBAdvertisementDataNameKey:localName}];
對應的值是數組
key: kCBAdvDataIsConnectable, value: 1
key: kCBAdvDataLocalName, value: SimpleBLEPeripheral
key: kCBAdvDataServiceUUIDs //數據就在這里
uuid(0): FF F0
key: kCBAdvDataTxPowerLevel, value: 0
Manufacturer Specific Data
NSArray *keys = [advertisementData allKeys];
NSData *dataAmb, *dataObj;
//獲取所有的key
for (int i = 0; i < [keys count]; ++i) {
id key = [keys objectAtIndex: i];
NSString *keyName = (NSString *) key;
NSObject *value = [advertisementData objectForKey: key];
//處理所有的value
if ([value isKindOfClass: [NSArray class]]) {
printf(" key: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding]);
NSArray *values = (NSArray *) value;
//處理每個value里面的值
for (int j = 0; j < [values count]; ++j) {
if ([[values objectAtIndex: j] isKindOfClass: [CBUUID class]]) {
CBUUID *uuid = [values objectAtIndex: j];
NSData *data = uuid.data; //獲取到 uuid.data
if (j == 0) {
dataObj = uuid.data;
} else {
dataAmb = uuid.data;
}
printf(" uuid(%d):", j);
for (int j = 0; j < data.length; ++j)
printf(" %02X", ((UInt8 *) data.bytes)[j]);
printf("\n");
} else {
const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];
printf(" value(%d): %s\n", j, valueString);
}
}
} else {
const char *valueString = [[value description] cStringUsingEncoding: NSUTF8StringEncoding];
printf(" key: %s, value: %s\n", [keyName cStringUsingEncoding: NSUTF8StringEncoding], valueString);
}
}
藍牙周邊后台執行模式
想要作為一個周邊角色在后台工作,你需要在Info.plist文件中添加bluetooth-periphral到UIBackgroundModes關鍵字下。當你這么做了,系統會在你的app需要讀,寫,訂閱事件的時候喚醒它。
除了可以在后台喚醒app處理連接的中心的讀寫訂閱。藍牙中心庫還可以允許你的app在后台的時候廣播。但是你需要了解app在后台的廣播和在前台的廣播狀態不太一樣。特別的,當你的app在后台廣播時。
CBAdvertisementDataLocalNameKey 廣告鍵是被忽略的,而且local name也不會被廣播的
所以 CBAdvertisementDataServiceUUIDsKey中的服務UUID被放在一個“溢出”區,它們只能被明確搜索的iOS設備搜索到。
如果所有app都在后台廣播,你的app的包廣播頻率會變少。
When you start advertising peripheral data, the peripheral manager calls the peripheralManagerDidStartAdvertising(_:error:) method of its delegate object.
Data advertising is done on a “best effort” basis, because space is limited and there may be multiple apps advertising simultaneously. While your app is in the foreground, it can use up to 28 bytes of space in the initial advertisement data for any combination of the supported advertising data keys. If this space is used up, there are an additional 10 bytes of space in the scan response that can be used only for the local name (represented by the value of the CBAdvertisementDataLocalNameKey key). Note that these sizes do not include the 2 bytes of header information that are required for each new data type. Any service universally unique identifiers (UUIDs) contained in the value of the CBAdvertisementDataServiceUUIDsKey key that do not fit in the allotted space are added to a special “overflow” area; they can be discovered only by an iOS device that is explicitly scanning for them. While your app is in the background, the local name is not advertised and all service UUIDs are placed in the overflow area. The exact format of advertising and response data is defined in the Bluetooth 4.0 specification, Volume 3, Part C, Section 11.
當開始廣告外圍設備數據時,外圍設備管理器調用其委托對象的外圍信息管理器didstartadvertising (_:error:)方法。
數據廣告是在“盡最大努力”的基礎上進行的,因為空間有限,同時可能有多個應用程序在做廣告。當你的應用程序在前台時,它可以在初始廣告數據中使用最多28字節的空間來組合支持的廣告數據鍵。如果耗盡了這個空間,那么掃描響應中還有額外的10字節空間,只能用於本地名稱(由CBAdvertisementDataLocalNameKey鍵值表示)。注意,這些大小不包括每個新數據類型所需的2個字節的頭信息。在特定的“溢出”區域中添加不適合於分配的空間的CBAdvertisementDataServiceUUIDsKey鍵值中包含的任何服務通用惟一標識符(uuid);只有當iOS設備顯式地掃描它們時,才能發現它們。當您的應用程序在后台時,本地名稱沒有廣告,所有服務uuid都放置在溢出區域。廣告和響應數據的確切格式定義在藍牙4.0規范第3卷C部分第11節中。
在初始化中心或者周邊管理者的時候選擇是否需要支持狀態的保存和恢復
在初始化時指定CBCentralManagerOptionRestoreIdentifierKey選項,並為中心管理者提供一個字符串作為“恢復標識”就可以了:
myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier" }];
CBPeripheralManagerOptionRestoreIdentifierKey
恢復你的中心和周邊管理者
當你的app在后台被系統重啟時,你的第一件事就是根據“恢復標識”恢復適當的中心和周邊管理者就像他們第一次創建時一樣
當你的app被系統重啟時,你可以檢索系統為你的應用程序保留的中央管理器對象的所有恢復標識符,像這樣:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSArray *centralManagerIdentifiers = launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];
在拿到恢復標示符之后,只需要遍歷並恢復適當的中央管理者。
- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary *)state { NSArray *peripherals = state[CBCentralManagerRestoredStatePeripheralsKey]; ...