4

Я хочу подключиться к устройству BLE после того, как устройство выведено/завершено пользователем или системой/переустановлено в фоновом режиме.Повторное подключение BLE

Я знаю, что это возможно: - see this question with description

Вопрос - Как я могу настроить centralManager для автоматического повторного подключения к периферийным в фоновом режиме, если приложение было прекращено? Может кто-нибудь описать шаг за шагом, как это можно сделать?

Несколько слов о текущей реализации:

Я создаю centralManager с опциями, как:

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.

В настоящее время, если я подключен к устройству и завершаю его - он автоматически перезапускается и подключается к устройству - все в порядке, но если оно завершено снова - ничего не происходит.

Также, если я перешел из периферии и вернусь - ничего не произошло.


Update

относительно точки 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 самому себе не к требуемому сервису.

Другим вопрос - это это хороший вариант, чтобы подключиться к периферийному времени потеряло соединение для поддержания связи, как:

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

Также попробуйте изменить уведомит характеристику на периферийном и прочитать его на устройстве. Если все сделано на переднем плане - все работает отлично, но в случае, если соединение было выполнено в фоновом режиме несколько раз didUpdateValueForCharacteristic не вызвано вообще, но didUpdateNotificationStateForCharacteristic вызывается без ошибок - это означает (я думаю), что что-то было сделано неправильно с моей стороны.Может быть, вы можете посоветовать, где проблема может быть

И еще один вопрос - есть ли какие-то ограничения в написании данных по характеристикам? потому что в образце яблока он настроен на 20 байтов.

ответ

13

Прежде всего, я хочу начать с того, что я работал с CoreBluetooth уже около двух лет и из того, что я заметил CoreBluetooth Сохранение и восстановление состояния не работает надежно вообще. Вы можете заставить его работать «нормально», но вы никогда не получите его, чтобы повторно подключиться надежно, если Apple не исправит его когда-нибудь.

Сказав это, я хочу отметить несколько вещей о вашей настройке.

1) В centralManager:willRestoreState: вы можете получать только периферийные устройства, которые совершили какое-либо сообщение, когда приложение было прервано. Это означает, что вы также должны реализовать centralManagerDidUpdateState:, а если состояние CBCentralManagerStatePoweredOn, то вы можете использовать метод retrievePeripheralsWithIdentifiers: для извлечения другого периферийного устройства и сброса его делегата. Это, конечно же, означает, что где-то в вашем приложении вы должны где-то хранить периферийные идентификаторы. Также не забудьте также перезагрузить ожидающие подключения.

2) Вы назначили делегату нуль в centralManager:willRestoreState:! Так что даже если он подключится, вы не узнаете об этом. I: P

3) Ваше приложение будет перезагружено, только если приложение было прервано системой. Он не будет перезапущен, если вы вручную удалите его из списка приложений. К сожалению, он не перезагрузится, если устройство перезагрузится.

4) CBConnectPeripheralOptionNotifyOnConnectionKey не требуется при использовании режима фонового режима bluetooth и просто раздражает пользователя, поэтому я бы не использовал его.

5) CBCentralManagerRestoredStatePeripheralsKey, CBCentralManagerRestoredStateScanServicesKey, CBCentralManagerRestoredStateScanOptionsKey не допустимые параметры инициализации, так что я не понимаю, почему вы используете те ..

5) Если Bluetooth переключает состояние в то время как приложение завершается, то все ожидающие соединения будут быть потерянным, и вы не будете возобновлены, чтобы знать об этом. Это само по себе эффективно означает, что государственное восстановление бесполезно.

Во всяком случае, мне грустно это говорить, но если вы разрабатываете приложение, которое должно полагаться на периферийное соединение, которое было вновь подключено в фоновом режиме, то я не рекомендую это делать. Вы будете разочарованы. Возможно, я мог бы написать эссе о всех ошибках в Core Bluetooth, которые Apple не хочет исправлять. Еще страшнее то, что вы можете довольно легко разрушить соединение Bluetooth на глобальном уровне с одного приложения, чтобы ни одно приложение не могло использовать bluetooth до перезагрузки устройства. Это довольно плохо, так как это противоречит принципу «яблок», разработанному Apple.

Если вам нужна дополнительная помощь, просто дайте мне знать!

/A

+0

Большое спасибо за ваш ответ. Я обновляю свой код - в настоящее время он выглядит как работающий нормально, если я не удаляю форму приложения «стек приложений». Пожалуйста, см. Обновление в вопросе – gbk

+0

Что касается номера 3 выше, действительно, к сожалению, в документации Core Bluetooth четко не указано «Эй, ваше приложение должно быть в списке MRU/приостановленных приложений », но он говорит такие вещи, как« система пробуждает его из приостановленного состояния, чтобы он мог обрабатывать события, связанные с Bluetooth », что, кажется, является их способом сказать вам, что , Во всяком случае, @Anton благодарит за ваш ответ. Я уверен, что это поможет многим другим, борющимся с этим аспектом разработки с iOS и BLE с Core Bluetooth! :) –

+0

Спасибо Антон. Apple еще не обновила свои api? –

Смежные вопросы