Базовая реклама Bluetooth и сканирование в фоновом режиме
Я пытался настроить приложение, чтобы устройство одновременно сканировало периферию и рекламировало как периферийное устройство. Цель состоит в том, чтобы два устройства просыпались в фоновом режиме, когда они находились рядом друг с другом через обнаружение Bluetooth. Из документации Apple кажется, что вы должны иметь возможность запускать BLE в фоновом режиме (с включенными режимами bluetooth-central и bluetooth-периферийный фон), и мое приложение работает, когда одно устройство находится на переднем плане. Во-первых, я рекламирую данные так:
NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey:@"my-peripheral",
CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:identifier]]};
// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];
Затем я настроил устройство для сканирования данных:
NSArray *services = @[[CBUUID UUIDWithString:identifier]];
[centralManager scanForPeripheralsWithServices:services options:nil];
Однако, когда оба уходят в фоновый режим (устройство должно быть заблокировано), Bluetooth не может обнаружить и
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
никогда не вызывается ни на одном устройстве. Как я могу это исправить? Спасибо
3 ответа
Боюсь, то, что вы пытаетесь сделать, не сработает. Я пытался добиться того же.
Проблема заключается в разнице в сканировании на переднем и заднем плане. Когда вы сканируете устройства на переднем плане, вы можете сканировать что угодно. В фоновом режиме вы должны указать фактический UUID службы, который вы сканируете. Хорошо, это на самом деле не проблема, так как вы знаете UUID, который вы ищете.
Периферийные. Вещание как периферийное устройство снова работает по-разному на переднем и заднем плане. На переднем плане это работает как любая нормальная периферия BT. В фоновом режиме он имеет очень ограниченное пространство для работы, поэтому UUID вашей периферии скрыт и не транслируется. Только когда центральное устройство (iPhone на переднем плане) запрашивает информацию от него, оно разбудит ваше приложение и покажет его UUID.
Таким образом, 2 отменяют друг друга. Поскольку фоновое сканирование может сканировать только устройства с определенным UUID, а фоновое периферийное устройство не может объявить свой UUID, они не могут видеть друг друга.
1 из ваших устройств (периферийных или центральных) должны быть на переднем плане для работы.
Это обсуждалось несколько раз в списке рассылки Apple Bluetooth.
Вы должны уточнить, как вы это тестируете, потому что теоретически похоже, что это должно работать. Есть две основные проблемы, с которыми вы можете столкнуться:
1.) Сканирование замедляется, когда устройства iOS находятся в фоновом режиме.
- Хотя сканирование на переднем плане, скорее всего, сразу же обнаружит рекламу устройства рядом с ним, обнаружение в фоновом режиме может занять до ~60 раз дольше. Система iOS не делает никаких предположений о том, что пользователь предпочел бы, чтобы одно приложение имело лучшую функциональность Bluetooth, чем другое (или что только одно приложение хочет использовать его). А поскольку это общая функциональность, они хотят, чтобы пользователи имели одинаковый опыт работы с приложениями. Вам следует ознакомиться с техническими характеристиками, касающимися интервалов между рекламой и сканированием, чтобы лучше понять, что Apple должна делать под прикрытием.
2.) Ваши устройства, возможно, уже обнаружили друг друга перед входом в фоновый режим.
- Мы должны помнить, что Apple отключает
CBCentralManagerScanOptionAllowDuplicatesKey
флаг сканирования, когда мы входим в фон. Поскольку вы даже не указываете этот флаг, по умолчанию он по умолчанию равен NO. Так что, если они даже видели друг друга один раз, вы не получите другой обратный вызов, когда они находятся в фоновом режиме.
Мне лично нужна была такая функция, и я разработал компонент с открытым исходным кодом: https://github.com/omergul123/Discovery
Это может быть очень полезно, если вы хотите обменяться идентификатором, даже если одноранговые приложения работают в фоновом режиме.