运行iPhone作为背景的​​iBeacon显示 [英] Run iPhone as an iBeacon in the background

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

问题描述

是否有可能运行在iOS 7设备作为蓝牙LE外围设备(iBeacon显示),并有在后台做广告?我已经能够得到它与下面的code前景做广告,可以看到它从其他iOS设备,但只要我回到主屏幕停止广告。我没有添加蓝牙外设背景模式的plist中,但似乎并没有帮助,虽然我得到提示说该设备要在后台使用蓝牙。我是不是做错了什么或者这只是不可能在iOS的7?

  peripManager = [[CBPeripheralManager页头] initWithDelegate:自队列:无]; - (无效)peripheralManagerDidUpdateState:(CBPeripheralManager *)外设
{
  如果(peripheral.state!= CBPeripheralManagerStatePoweredOn){
      返回;
  }  * NSString的标识符= @MyBeacon
  //构建区域
  CLBeaconRegion * beaconRegion = [[CLBeaconRegion页头] initWithProximityUUID:UUID标识:标识]。  //传递零将使用设备默认的电源
  * NSDictionary的有效载荷= [beaconRegion peripheralDataWithMeasuredPower:无];  //开始广告
  [peripManager startAdvertising:有效载荷]。
}

下面是code是在接收/收听结束:

   - (空)的LocationManager:(CLLocationManager *)经理didRangeBeacons:(NSArray的*)标
           inRegion:(CLBeaconRegion *)区域
{
//检查我们是否移近或远离iBeacon显示...
如果(beacons.count大于0){
    CLBeacon *信标= [信标objectAtIndex:0];    开关(beacon.proximity){
        案例CLProximityImmediate:
            [self日志:[的NSString stringWithFormat:@!你坐在它立%,(长)beacon.rssi]];
            打破;
        案例CLProximityNear:
            [self日志:[的NSString stringWithFormat:@!逐渐回暖%礼,(长)beacon.rssi]];
            打破;
        默认:
            [self日志:[的NSString stringWithFormat:@!这是在这附近立%,(长)beacon.rssi]];
            打破;
    }
}
}


解决方案

标准CoreBluetooth广告可以播放,而应用程序是在后台运行,但如果他们开始与 CLBeaconRegion 词典。解决办法是干脆抛弃CoreLocation框架,并创建自己的近水楼台框架只用CoreBlueTooth。

您还需要使用适当的背景说明符的Info.plist文件(例如:蓝牙外设蓝牙中央)。

在code看起来是这样的:

1),使用创建一个标准的外围广告 CBPeripheralManager

 的NSDictionary * advertisingData = @ {CBAdvertisementDataLocalNameKey:@我外设
                                  CBAdvertisementDataServiceUUIDsKey:@ [CBUUID UUIDWithString:标识符]};//超过BLE开始投放广告
[peripheralManager startAdvertising:advertisingData];

2)使用使用 CBCentralManager 使用指定的UUID以扫描服务。

 的NSDictionary * scanOptions = @ {CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
NSArray的*服务= @ [CBUUID UUIDWithString:标识符]];[centralManager scanForPeripheralsWithServices:服务选项:scanOptions];

3) CBCentralManagerDelegate 方法 didDiscoverPeripheral ,阅读 RSSI 广告的价值。

   - (无效)centralManager:(CBCentralManager *)中央didDiscoverPeripheral:(CBPeripheral *)外设
     advertisementData:(NSDictionary的*)advertisementData RSSI(NSNumber的*)RSSI
{    的NSLog(@RSSI数:%d,[RSSI的intValue]);
}

4)翻译的RSSI值成距离

   - (INDetectorRange)convertRSSItoINProximity:(NSInteger的)接近
{
    如果(接近< -70)
        返回INDetectorRangeFar;
    如果(接近< -55)
        返回INDetectorRangeNear;
    如果(接近℃,)
        返回INDetectorRangeImmediate;    返回INDetectorRangeUnknown;
}

我发现我需要放松或平均的RSSI值得到任何可行的。这绝不是当你与任何传感器数据的工作(例如加速计数据),比不同。

我有这个概念完全工作,希望在某个时候某个地​​方发表。

此外,使用docs (蓝牙核心编程指南),如果你会被卡住。

更新::一种满code样品达Github上。我从事这是一个工作相关的项目的一部分。

更新#2: 苹果释放到iBeacon显示后台行为主要改进为iOS7.1

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

解决方案

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.

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

The code looks something like this:

1) create a standard peripheral advertisement using CBPeripheralManager

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

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

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

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.

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

Update #2: Apple release major improvements to iBeacon background behavior for iOS7.1

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

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