我在理解iOS应用程序后台扫描时遇到了一些困难。我有一个非常简单的测试应用程序,只是扫描设备并将结果输出到控制台。我已经在Info.plist中添加了bluetooth-central作为必需的后台模式,所以应该没问题。我正在扫描具有一个指定服务的设备,即
NSArray *cbuuidArray = [NSArray arrayWithObjects:[CBUUID UUIDWithString:@"UUIDFromUUIDGEN"],nil];
[self.centralManager scanForPeripheralsWithServices:cbuuidArray options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
当应用程序在前台时,我只连接了一个(或零个)BLE设备到电源上,因此iOS会经常检测并显示结果。当我进入后台时,第一个设备的结果不再显示,这是预期的,因为设置了CBCentralManagerScanOptionAllowDuplicatesKey
为NO。
此时,我正在给第二个BLE设备供电,并急切地等待它出现在结果中。等了10分钟什么也没有。我的应用程序没有被终止,因为我的最后一个通知来自于applicationDidEnterBackground
,而且在任务进行时从未调用applicationWillTerminate
。
在一个偶然的机会中,我发现如果我的应用程序在后台运行并且仍在扫描,另一个BLE扫描应用程序(我使用优秀的BLExplr)在前台并开始扫描,我的应用程序最终会在与前台应用程序相同的时间收到结果。这是有道理的,因为广告数据包由系统处理并分派到应用程序,但为什么我的应用程序自己不接收任何数据呢?
是否有人有类似的经验或知道这可能是由什么原因引起的?我已经阅读了所有关于后台和蓝牙的苹果资源,但是没有任何关于此问题的提示。我正在使用iOS 4s和iOS 5.1.1。我的主要ViewController
是一个CBCentralManagerDelegate
委托,看起来像这样。
@implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
return self;
}
#pragma mark -
#pragma mark CBCentralManagerDelegate methods
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if( central.state == CBCentralManagerStatePoweredOn ){
NSArray *cbuuidArray = [NSArray arrayWithObjects:
[CBUUID UUIDWithString:@"UUID"],
nil];
[self.centralManager scanForPeripheralsWithServices:cbuuidArray options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"%s / peripheral: %@, adData: %@, RSSI: %@" , __PRETTY_FUNCTION__ , peripheral, advertisementData, RSSI);
NSLog(@"Periphal name: %@", peripheral.name);
}
#pragma mark -
#pragma mark CBPeripheralDelegate methods
@end
在应用程序中除了在应用程序委托中初始化NavigationController
之外,没有其他更多的事情发生。