Запустите iPhone как iBeacon в фоновом режиме
Можно ли запустить устройство iOS 7 в качестве периферийного устройства Bluetooth LE (iBeacon) и разместить его в фоновом режиме? Мне удалось заставить его показывать рекламу на переднем плане с помощью приведенного ниже кода, и я вижу его с другого устройства iOS, но как только я возвращаюсь на домашний экран, он прекращает рекламу. Я добавил фоновый режим bluetooth-периферийное устройство, но это, похоже, не помогло, хотя я получаю подсказку о том, что устройство хочет использовать bluetooth в фоновом режиме. Я делаю что-то не так или это просто невозможно в iOS 7?
peripManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
return;
}
NSString *identifier = @"MyBeacon";
//Construct the region
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:identifier];
//Passing nil will use the device default power
NSDictionary *payload = [beaconRegion peripheralDataWithMeasuredPower:nil];
//Start advertising
[peripManager startAdvertising:payload];
}
Вот код, который находится на стороне приема / прослушивания:
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region
{
//Check if we have moved closer or farther away from the iBeacon…
if (beacons.count > 0) {
CLBeacon *beacon = [beacons objectAtIndex:0];
switch (beacon.proximity) {
case CLProximityImmediate:
[self log:[NSString stringWithFormat:@"You're Sitting on it! %li", (long)beacon.rssi]];
break;
case CLProximityNear:
[self log:[NSString stringWithFormat:@"Getting Warmer! %li", (long)beacon.rssi]];
break;
default:
[self log:[NSString stringWithFormat:@"It's around here somewhere! %li", (long)beacon.rssi]];
break;
}
}
}
5 ответов
Стандартная реклама CoreBluetooth может транслироваться, пока приложение находится в фоновом режиме, но не в том случае, если оно было запущено с CLBeaconRegion
толковый словарь. Обходной путь состоит в том, чтобы полностью отказаться от инфраструктуры CoreLocation и создать свою собственную "структуру" близости, используя только CoreBlueTooth.
Вам все еще нужно использовать соответствующие спецификаторы фона в файле Info.plist (например, bluetooth-peripheral
а также bluetooth-central
).
Код выглядит примерно так:
1) создать стандартную периферийную рекламу, используя CBPeripheralManager
NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey:@"my-peripheral",
CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:identifier]]};
// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];
2) использовать использовать CBCentralManager
сканировать эту службу, используя указанный вами UUID.
NSDictionary *scanOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
NSArray *services = @[[CBUUID UUIDWithString:identifier]];
[centralManager scanForPeripheralsWithServices:services options:scanOptions];
3) в CBCentralManagerDelegate
метод didDiscoverPeripheral
прочитайте RSSI
стоимость рекламы.
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"RSSI: %d", [RSSI intValue]);
}
4) Переведите значения RSSI в расстояние.
- (INDetectorRange)convertRSSItoINProximity:(NSInteger)proximity
{
if (proximity < -70)
return INDetectorRangeFar;
if (proximity < -55)
return INDetectorRangeNear;
if (proximity < 0)
return INDetectorRangeImmediate;
return INDetectorRangeUnknown;
}
Я обнаружил, что мне нужно "облегчить" или "усреднить" значения RSSI, чтобы получить что-либо работоспособное. Это ничем не отличается от того, когда вы работаете с любыми данными датчиков (например, данными акселерометра).
У меня есть эта концепция, полностью работающая, надеюсь опубликовать ее где-нибудь в какой-то момент
Кроме того, используйте документацию (Базовое руководство по программированию Bluetooth), если вы застряли.
Обновление: полный пример кода на Github. Я работал над этим как часть проекта, связанного с работой.
Обновление № 2: Apple выпустила значительные улучшения фонового поведения iBeacon для iOS7.1
Вы можете чувствовать запах iBeacon? В статье рассматриваются как использование Estimotes, так и реклама с Mac и iOS-устройств. Вам нужно проверить возможность "Действует как аксессуар Bluetooth LE" в цели проекта.
Нет, устройства iOS рекламируют iBeacon только тогда, когда приложение, которое делает рекламу, работает на переднем плане. поэтому, если вы переключаетесь на другое приложение или устройство переходит в спящий режим, реклама прекращается.
Конечно, если вы действительно хотите, чтобы реклама продолжалась, отключите таймер простоя и выполните Guided Access, чтобы устройство iOs не переходило в спящий режим и никто не мог переключиться на другое приложение.
Я также надеюсь, что смогу настроить свое (тестовое) приложение для рекламы iBeacon из фона. Документы на ключ info.plist UIBackgroundModes предполагают, что ключ bluetooth-периферийное устройство может работать, но кажется, что это не так. (Я только что проверил это несколько минут назад.)
Сейчас я делаю отключение таймера простоя, как предлагает RawMean, и затем устанавливаю яркость экрана на 0. Наконец, когда мое тестовое приложение работает как iBeacon, я добавляю обработчик события встряхивания, который освещает экран. снова на 30 секунд. Уменьшение яркости экрана до некоторой степени помогает уменьшить разрядку аккумулятора.
Это можно сделать. Я не хочу злых инженеров Apple у моего порога, поэтому я не буду публиковать алгоритм.
Таким образом, область переполнения, которая кодирует идентификаторы UUID службы, представляет собой просто набор байтов, передаваемых по воздуху. Вы можете понюхать это сами. В частности, это короткий хеш, который впоследствии представляется одним горячим кодированием. Множество UUID передаются посредством установки нескольких битов. У вас будут столкновения таким образом. Например, код UUID 1001 будет иметь ту же кодировку, что и 3333. Вы можете проверить это сами: на iPhone транслируется UUID 1001 на заднем плане, а другой сканирует на 3333. Он будет думать, что он действительно получает 3333.