iOS蓝牙常驻后台-那些你可能遇到的坑

APP进入后台后,蓝牙扫描必须指明servicesId

    NSArray *servicesArray = @[[CBUUID UUIDWithString:D_Transfer_Service_UUID]];
    [self.centralManager scanForPeripheralsWithServices:servicesArray
                                                options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @(YES)}];
  • 当APP处于前台时,如果第一个参数设置成nil,那么centralManager会返回所有被发现的外设,否则,只有有广播这些uuid服务的外设才会被返回;
  • 当APP处于后台时,如果第一个参数为nil,那么centralManager不会返回任何外设,因此如果你希望你的APP支持蓝牙后台运行,那么你需要设置明确的servicesId

APP进入后台后,只能扫描到广播包扫不到扫描包

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
  • 外设进行广播时,广播内容包括广播包和扫描包
  • 当APP处于前台时,蓝牙可以扫到外设广播的全部内容,即:advertisementData实际上整合了外设广播的广播包和扫描包
  • 当APP处于后台时,蓝牙只能扫到外设广播的广播包,扫不到扫描包,即:advertisementData只包含广播包内容,所以如果你的APP需要支持后台运行,那么你需要告知嵌入式工程师把广播内容全部放到广播包中

外设名称更改后,扫描到的仍然是旧的名称

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

假设外设初始名称为WatchName-A,你用WatchName-A进行了扫描连接,然后嵌入式工程师把外设名称更改为WatchName-B,你再次扫描时会发现你扫描到的设备名仍然是WatchName-A,这时无论你重启手机蓝牙还是重启手机都会发现设备名依然是WatchName-A,因此如果你在发现设备后通过[peripheral.name isEqualToString:@"WatchName-B"]来确定你的设备,你将会错误的认为外设坏了没有进行广播,因此更安全的方法是你通过广播包中的名称来确定你的设备名,即:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    NSData *manufacturerData = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
    NSString *name = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
    if ([name isEqualToString:@"WatchName-B"] || [peripheral.name isEqualToString:@"WatchName-B"]) {
        ...
    }
    ...
}

你可能感兴趣的:(iOS蓝牙常驻后台-那些你可能遇到的坑)