BLE背景重新连接
在用户或系统移出/终止设备后,我想重新连接到BLE设备/在后台模式下重新绑定。
我知道这是可能的: – 看到这个问题的描述
问题 – 如何设置centralManager
自动重新连接到外设在后台模式,如果应用程序被终止? 有人可以一步一步描述如何做到这一点?
关于当前实施的几句话:
我使用以下选项创buildcentralManager:
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier", CBCentralManagerRestoredStatePeripheralsKey : @YES, CBCentralManagerRestoredStateScanServicesKey : @YES, CBCentralManagerRestoredStateScanOptionsKey : @YES }];
之后,我开始扫描BLE设备
[self.centralManager scanForPeripheralsWithServices:[self discoverableCharacteristics] options:nil];
在- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
我连接到外设:
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]; [self.centralManager stopScan]; peripheral.delegate = self; [self.centralManager connectPeripheral:peripheral options: @{ CBConnectPeripheralOptionNotifyOnNotificationKey : @YES }];
之后,我可以发现服务和特点 – 所有看起来像确定。 当我发现特性和读取/写入数据我cancelPeripheralConnection
在didDisconnect我重新连接到设备
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error { [central connectPeripheral:peripheral options:nil]; }
我也实现了centralManager:willRestoreState:
就像:
NSArray *peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]; for (CBPeripheral *peripheral in peripherals) { [central connectPeripheral:peripheral options:nil]; peripheral.delegate = nil; }
在plist。 添加所需的关键App communicates using CoreBluetooth
。
目前,如果我连接到设备并终止它 – 自动重新启动并连接到设备 – 一切正常,但如果它再次终止 – 什么都没有发生。
另外,如果我从外围移出,并回来 – 什么都没有发生。
更新
关于第5点 – 我的秋天 – 应该用connectPeripheral
来使用这个键
在WillRestoreState:
NSArray *peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey]; if (!peripherals.count) { peripherals = [central retrievePeripheralsWithIdentifiers:[self discoverableCharacteristics]]; } if (peripherals.count) { for (CBPeripheral *peripheral in peripherals) { [central connectPeripheral:peripheral options:@{ CBCentralManagerRestoredStatePeripheralsKey : @YES, CBCentralManagerRestoredStateScanServicesKey : @YES, CBCentralManagerRestoredStateScanOptionsKey : @YES }]; } } else { [self startScanning]; }
目前的结果 – 应用程序将重新启动,如果它没有从托盘中刷出。 我使用我的Mac作为外设,所以有时候我不启动应用程序,使外设中心的作用可以连接到Mac本身而不是所需的服务。
另外一个问题 – 重新连接外围设备是否是一个好的select,而丢失连接可以保持连接,如:
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error { [central connectPeripheral:peripheral options:@{ CBCentralManagerRestoredStatePeripheralsKey : @YES, CBCentralManagerRestoredStateScanServicesKey : @YES, CBCentralManagerRestoredStateScanOptionsKey : @YES }]; }
也尝试改变外设的通知特性并在设备上读取。 如果全部在前台完成 – 所有的工作都很完美,但是如果连接在后台完成,有时候didUpdateValueForCharacteristic
没有调用didUpdateNotificationStateForCharacteristic
,但是没有错误地调用didUpdateNotificationStateForCharacteristic
– 这意味着(我认为)在我身边做了错误的事情。 也许你可以build议哪里可以解决问题
还有一个问题 – 在将数据写入特性方面有一些限制吗? 因为在苹果示例中,它被设置为20个字节。
首先,我想先说我已经使用CoreBluetooth大约两年了,从我注意到,CoreBluetooth State Preservation和Restoration不能可靠地工作。 你可以得到它的工作“好”,但你永远不会得到它可靠地重新连接,除非苹果有一天修复它。
话虽如此,我想在你的设置上注意一些事情。
1)在centralManager:willRestoreState:
你只能检索已经完成任何沟通,而应用程序被终止的外设。 这意味着你也应该实现centralManagerDidUpdateState:
如果状态是CBCentralManagerStatePoweredOn
那么你可以使用retrievePeripheralsWithIdentifiers:
方法来检索其他外围设备并重置它们的委托。 这当然意味着你必须在你的应用程序某处存储外设标识符。 还记得在这里重置挂起的连接。
2)在centralManager:willRestoreState:
设置为nil centralManager:willRestoreState:
所以,即使它连接,你也不会知道它我:P
3)如果应用程序被系统终止,您的应用程序将只会重新启动。 如果您从应用程序列表中手动刷卡,它将不会重新启动。 不幸的是,如果设备重新启动,它也不会重新启动。
4)当使用蓝牙中央背景模式时, CBConnectPeripheralOptionNotifyOnConnectionKey
不是必需的,只是烦人的用户,所以我不会使用它。
5) CBCentralManagerRestoredStatePeripheralsKey
, CBCentralManagerRestoredStateScanServicesKey
, CBCentralManagerRestoredStateScanOptionsKey
是无效的初始化选项,所以我不明白你为什么使用这些..
5)如果蓝牙切换状态,而应用程序被终止,那么所有挂起的连接将会丢失,你将不会重新启动了解它。 这本身就意味着国家恢复是无用的。
无论如何,我很难过这么说,但是如果你正在开发一个应用程序,必须依赖于在后台重新连接的外设,那么我不会推荐这样做。 你会感到沮丧。 我大概可以写一篇关于苹果公司不想解决的核心蓝牙问题的文章。 更可怕的是,你可以从一个单一的应用程序很容易地破坏设备上的全球蓝牙连接,以便没有应用程序可以使用蓝牙,直到设备重新启动。 这是非常糟糕的,因为它违背了苹果自己的沙箱原则。
如果您需要任何帮助,请告诉我!
/一个