0

我正在开发一个测试 BTLE 应用程序。用户可以选择启动中央或外围模式。如果 2 个设备都处于活动状态并且在范围内,它们会立即检测、连接和传递数据,但是......

如果 device1 在中心模式下启动,然后进入后台,则 device2 将超出范围并进入外围模式,当外围设备靠近后台中心时,中心检测外围设备并获取数据。

如果 device1 以外围模式启动并置于后台,则 device2 会超出范围并置于中央模式,然后进入范围,它不会检测到外围设备。(我最多等了 5 分钟)如果我再次按下“启动中央”按钮,它会立即检测到!

“启动中心”仅执行以下操作:

-(id)init{
    if (self=[super init]) {
        dispatch_queue_t peripheralQueue=dispatch_queue_create("com.Dev.peripheralQueue", 0);
        dispatch_queue_t centralQueue=dispatch_queue_create("com.Dev.centralQueue", 0);

        // Initiate Managers with restore keys for background mode
        self.centralManager=[[CBCentralManager alloc]initWithDelegate:self
                                                                queue:centralQueue
                                                              options:@{CBCentralManagerOptionRestoreIdentifierKey: CM_RESTORE_KEY}];
        self.peripheralManager=[[CBPeripheralManager alloc]initWithDelegate:self
                                                                      queue:peripheralQueue
                                                                    options:@{CBPeripheralManagerOptionRestoreIdentifierKey: PM_RESTORE_KEY}];
        // 1. create The UUIDs
        // 2. create the service and characteristics
//service is alloc/inited and published in did update state
    }
    return self;
}

-(void)switchToCentral
{
    NSLog(@"BTM switchToCentral");
    [self.peripheralManager stopAdvertising];
    [self scan];
    self.isCentral = YES;
}

- (void)scan
{
    [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]
                                                options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@NO}];
    NSLog(@"CM Scanning started");
}

我添加了以下可耻的 hack:

-(void)switchToCentral
{
    NSLog(@"BTM switchToCentral");
    [self stopBroadcasting];
    [self scan];
    self.isCentral = YES;

    dispatch_async(dispatch_get_main_queue(), ^{
        [NSTimer scheduledTimerWithTimeInterval:5
                                         target:self
                                       selector:@selector(centralShouldRescan:)
                                       userInfo:nil
                                        repeats:YES];
    });
}

-(void)centralShouldRescan:(NSTimer*)timer{

    NSLog(@"BTM centralShouldRescan");
    if (self.isCentral) {
        NSLog(@"BTM centralShouldRescan isCentral");
        [self stopBroadcasting];
        [self scan];


    }else{
        NSLog(@"BTM centralShouldRescan isCentral");
        [timer invalidate];
    }
}

现在它可以工作了!我对此感到茫然。根据我的理解和经验,当 CBCentral 管理器开始扫描时,它会一直扫描直到停止,尤其是在前台时。

4

1 回答 1

1

你实现了centralManagerDidUpdateState委托方法吗?我怀疑当您禁用外围模式时,在 centralManager 准备好扫描之前会有一些时间延迟 - 这只是一个猜测。你可以尝试类似的东西 -

-(void) centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (central.state == CBCentralManagerStatePoweredOn)
    {
       [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@NO}];
    }
}

如果中央管理器从通电状态转换,这将确保重新启动扫描。

于 2014-03-31T03:50:49.383 回答