Reconnection de background BLE

Quiero volver a conectar con el dispositivo BLE después de que el dispositivo se mueva o termine por el usuario o el sistema / se rebotó en el modo de background.

Sé que es posible: – ver esta pregunta con la descripción

Pregunta: ¿Cómo puedo configurar centralManager para volver a conectar automáticamente a los periféricos en modo de background si la aplicación se termina? ¿Alguien puede describir paso a paso cómo se puede hacer?

Pocas palabras sobre la implementación actual:

Creo centralManager con opciones como:

 self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:@{ CBCentralManagerOptionRestoreIdentifierKey: @"myCentralManagerIdentifier", CBCentralManagerRestonetworkingStatePeripheralsKey : @YES, CBCentralManagerRestonetworkingStateScanServicesKey : @YES, CBCentralManagerRestonetworkingStateScanOptionsKey : @YES }]; 

Después de eso, empiezo a escanear el dispositivo BLE

 [self.centralManager scanForPeripheralsWithServices:[self discoverableCharacteristics] options:nil]; 

in - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI me conecto a periférico:

  NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey]; [self.centralManager stopScan]; peripheral.delegate = self; [self.centralManager connectPeripheral:peripheral options: @{ CBConnectPeripheralOptionNotifyOnNotificationKey : @YES }]; 

Después de eso, puedo descubrir services y características, todo parece estar bien. Cuando descubro datos característicos y de lectura / escritura cancelPeripheralConnection

en didDisconnect i vuelva a conectar al dispositivo

 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error { [central connectPeripheral:peripheral options:nil]; } 

También implemento centralManager:willRestoreState: like:

 NSArray *peripherals = dict[CBCentralManagerRestonetworkingStatePeripheralsKey]; for (CBPeripheral *peripheral in peripherals) { [central connectPeripheral:peripheral options:nil]; peripheral.delegate = nil; } 

En plist La key adicional requerida se App communicates using CoreBluetooth .

Actualmente, si me conecté al dispositivo y lo termino, se reinicia automáticamente y se conecta al dispositivo, todo está bien, pero si termina de nuevo, no sucede nada.

Además, si me mudé de periférico y vuelvo, no pasó nada.


Actualizar

Con respecto al punto 5 – mi caída – debería usar esta key con connectPeripheral

en WillRestoreState:

 NSArray *peripherals = dict[CBCentralManagerRestonetworkingStatePeripheralsKey]; if (!peripherals.count) { peripherals = [central retrievePeripheralsWithIdentifiers:[self discoverableCharacteristics]]; } if (peripherals.count) { for (CBPeripheral *peripheral in peripherals) { [central connectPeripheral:peripheral options:@{ CBCentralManagerRestonetworkingStatePeripheralsKey : @YES, CBCentralManagerRestonetworkingStateScanServicesKey : @YES, CBCentralManagerRestonetworkingStateScanOptionsKey : @YES }]; } } else { [self startScanning]; } 

Resultado actual: la aplicación se relanzará si no se extrae de la bandeja. Uso mi Mac como un periférico, así que algunas veces cuando no lanzo una aplicación que hace que el rol de periférico central pueda conectarse a Mac, no al service requerido.

Otra pregunta: ¿es una buena opción volver a conectarse a periféricos mientras se pierde la connection para mantener la connection como:

 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error { [central connectPeripheral:peripheral options:@{ CBCentralManagerRestonetworkingStatePeripheralsKey : @YES, CBCentralManagerRestonetworkingStateScanServicesKey : @YES, CBCentralManagerRestonetworkingStateScanOptionsKey : @YES }]; } 

También intente cambiar la característica de notificación en el periférico y leerlo en el dispositivo. Si todo se hace en primer plano, todo funciona perfectamente, pero en caso de que la connection se haya hecho en segundo plano, algunas veces didUpdateValueForCharacteristic no se llama en absoluto, pero didUpdateNotificationStateForCharacteristic se llama sin error; esto significa (creo) que algo se hizo mal a mi lado. Tal vez puedas aconsejar dónde puede ser un problema

Y una pregunta más: ¿hay alguna restricción en la networkingacción de los datos a las características? porque en la muestra de Apple está configurado a 20 bytes.

En primer lugar, quiero comenzar diciendo que he estado trabajando con CoreBluetooth por cerca de dos años y por lo que he notado que CoreBluetooth State Preservation and Restoration no funciona de manera confiable en absoluto. Puede hacer que funcione como "ok", pero nunca lo volverá a conectar de manera confiable a less que Apple lo arregle algún día.

Dicho esto, quiero señalar algunas cosas en su configuration.

1) En centralManager:willRestoreState: solo puede recuperar los periféricos que hayan realizado alguna comunicación mientras la aplicación finalizó. Esto significa que también debe implementar centralManagerDidUpdateState: y si el estado es CBCentralManagerStatePowenetworkingOn , puede usar el método retrievePeripheralsWithIdentifiers: método para recuperar el otro periférico y restablecer su delegado también. Por supuesto, esto significa que debe almacenar los identificadores periféricos en alguna parte de su aplicación. También recuerde restablecer las conexiones pendientes aquí también.

2) Configura el delegado en nil en centralManager:willRestoreState: Entonces, incluso si se conecta, no lo sabrás i: P

3) Su aplicación solo se relanzará si la aplicación fue cancelada por el sistema. No se relanzará si lo desliza manualmente y lo elimina de la list de aplicaciones. Tampoco se relanzará si el dispositivo se reinicia, por desgracia.

4) El CBConnectPeripheralOptionNotifyOnConnectionKey no es necesario cuando se usa el modo de background central de Bluetooth y es simplemente molesto para un usuario, por lo que no lo uso.

5) CBCentralManagerRestonetworkingStatePeripheralsKey , CBCentralManagerRestonetworkingStateScanServicesKey , CBCentralManagerRestonetworkingStateScanOptionsKey no son opciones de initialization válidas, así que no entiendo por qué estás usando esas …

5) Si el bluetooth cambia mientras la aplicación finaliza, todas las conexiones pendientes se perderán y no se relanzará para saberlo. Esto por sí solo significa que la restauración del estado es bastante inútil.

De todos modos, me entristece decirlo, pero si está desarrollando una aplicación que debe confiar en que el periférico se vuelva a conectar en segundo plano, entonces no recomendaría hacerlo. Te vas a frustrar Probablemente podría escribir un ensayo sobre todos los errores en Core Bluetooth que Apple no quiere corregir. Aún más aterrador es que fácilmente puede arruinar la conectividad bluetooth a nivel mundial en el dispositivo desde una única aplicación para que ninguna aplicación pueda usar bluetooth hasta que se reinicie el dispositivo. Esto es bastante malo, ya que va en contra del principio de Sandboxing de Apples.

Si necesita más ayuda, ¡solo hágamelo saber!

/UN