在后台将 iPhone 作为 iBeacon 运行 [英] Run iPhone as an iBeacon in the background

查看:20
本文介绍了在后台将 iPhone 作为 iBeacon 运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将 iOS 7 设备作为蓝牙 LE 外围设备 (iBeacon) 运行并让它在后台做广告?我已经能够使用下面的代码让它在前台做广告,并且可以从另一台 iOS 设备上看到它,但是一旦我回到主屏幕,它就会停止广告.我确实在 plist 中添加了蓝牙外设背景模式,但这似乎没有帮助,尽管我确实收到提示说设备想要在后台使用蓝牙.是我做错了什么,还是在 iOS 7 中这是不可能的?

Is it possible to run an iOS 7 device as a Bluetooth LE peripheral (iBeacon) and have it advertise in the background? I have been able to get it to advertise in the foreground with the code below and can see it from another iOS device but as soon as I go back to the home screen it stops advertising. I did add the bluetooth-peripheral background mode in the plist but that didn't seem to help although I do get the prompt saying the device wants to use bluetooth in the background. Am I doing something wrong or is this just not possible in 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];
}

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

Here is the code that is on the receiving/listening end:

- (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;
    }
}
}

推荐答案

标准 CoreBluetooth 广告可以在应用程序处于后台时广播,但如果它们以 CLBeaconRegion 字典启动,则不能广播.解决方法是完全放弃 CoreLocation 框架,仅使用 CoreBlueTooth 创建您自己的邻近框架".

Standard CoreBluetooth advertisements can broadcast while the app is in the background, but not if they were started with CLBeaconRegion dictionary. The workaround is to ditch CoreLocation framework altogether and create your own proximity "framework" using only CoreBlueTooth.

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

You still need to use the appropriate background specifiers in the Info.plist file (e.g. bluetooth-peripheral and bluetooth-central).

代码如下所示:

1) 使用 CBPeripheralManager

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

// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];

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

2) use use CBCentralManager to scan for that service using the UUID you specified.

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

[centralManager scanForPeripheralsWithServices:services options:scanOptions];

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

3) in the CBCentralManagerDelegate method didDiscoverPeripheral, read the RSSI value of the advertisement.

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

    NSLog(@"RSSI: %d", [RSSI intValue]);
}

4) 将 RSSI 值转换为距离.

4) Translate the RSSI values into a distance.

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

    return INDetectorRangeUnknown;
}

我发现我需要简化"或平均"RSSI 值才能得到任何可行的结果.这与您处理任何传感器数据(例如加速度计数据)时没有什么不同.

I found that I needed to "ease" or "average" the RSSI values to get anything workable. This is no different than when you are working with any sensor data (e.g. accelerometer data).

我有这个概念完全有效,希望在某个时候将其发布.

I have this concept fully working hope to publish it somewhere at some point.

此外,使用文档(核心蓝牙编程指南)如果你卡住了.

Also, use the docs (Core Bluetooth Programming Guide) if you get stuck.

更新:完整的代码示例已在 Github 上发布.我作为工作相关项目的一部分参与了这项工作.

Update: A full code sample is up on Github. I worked on this as part of a work related project.

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

这篇关于在后台将 iPhone 作为 iBeacon 运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆