在后台运行iPhone作为iBeacon

jpc*_*der 68 bluetooth ios bluetooth-lowenergy ibeacon

是否可以将iOS 7设备作为蓝牙LE外设(iBeacon)运行并在后台进行广告宣传?我已经能够使用下面的代码在前台做广告,并且可以从另一个iOS设备看到它但是一旦我回到主屏幕就停止广告.我确实在plist中添加了蓝牙外设背景模式,但这似乎没有帮助,虽然我得到提示说该设备想要在后台使用蓝牙.我做错了什么,或者这在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];
}
Run Code Online (Sandbox Code Playgroud)

这是接收/收听端的代码:

- (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;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

ben*_*ord 48

当应用程序在后台时,标准CoreBluetooth广告可以广播,但如果它们是以CLBeaconRegion字典开头的话,则不会.解决方法是完全抛弃CoreLocation框架,并仅使用CoreBlueTooth创建自己的邻近"框架".

您仍然需要在Info.plist文件中使用适当的背景说明符(例如bluetooth-peripheralbluetooth-central).

代码看起来像这样:

1)使用创建标准外围广告 CBPeripheralManager

NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey:@"my-peripheral",
                                  CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:identifier]]};

// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];
Run Code Online (Sandbox Code Playgroud)

2)使用use CBCentralManager使用您指定的UUID扫描该服务.

NSDictionary *scanOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
NSArray *services = @[[CBUUID UUIDWithString:identifier]];

[centralManager scanForPeripheralsWithServices:services options:scanOptions];
Run Code Online (Sandbox Code Playgroud)

3)在该CBCentralManagerDelegate方法中didDiscoverPeripheral,读取RSSI广告的值.

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{

    NSLog(@"RSSI: %d", [RSSI intValue]);
}
Run Code Online (Sandbox Code Playgroud)

4)将RSSI值转换为距离.

- (INDetectorRange)convertRSSItoINProximity:(NSInteger)proximity
{
    if (proximity < -70)
        return INDetectorRangeFar;
    if (proximity < -55)
        return INDetectorRangeNear;
    if (proximity < 0)
        return INDetectorRangeImmediate;

    return INDetectorRangeUnknown;
}
Run Code Online (Sandbox Code Playgroud)

我发现我需要"缓解"或"平均"RSSI值才能使任何事情变得可行.这与使用任何传感器数据(例如加速度计数据)时没有什么不同.

我有这个概念完全工作希望在某个时候在某个地方发布它.

此外,如果卡住,请使用docs(核心蓝牙编程指南).

更新:Github上有一个完整的代码示例.作为工作相关项目的一部分,我参与了此项工作.

更新#2: Apple发布了针对iOS7.1的iBeacon后台行为的重大改进

  • 不幸的是,当应用程序移至后台时,数据有效载荷(即iBeacon信息)被剥离。在iOS 7.0.5上测试。 (2认同)
  • 这实际上并不能使应用程序完全像iBeacon那样工作,对吗?就像它一样,它不支持Major / Minor值,传统的CoreLocation API也不会检测到它吗? (2认同)
  • @Yazid对。它不使用或不与传统的CoreLocation API一起使用。但是它确实允许您在支持后台广播和检测的同时在应用中复制iBeacon行为。 (2认同)

Raw*_*ean 2

不会,iOS 设备仅在执行广告的应用程序在前台运行时广告 iBeacon。因此,如果您切换到另一个应用程序或设备进入睡眠状态,广告就会停止。

当然,如果您确实希望广告继续,请禁用空闲计时器并执行引导访问,这样 iOs 设备就不会进入睡眠状态,并且没有人可以切换到另一应用程序。