Run iPhone as an iBeacon in the background

前端 未结 4 829
栀梦
栀梦 2020-11-29 14:54

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 foregro

4条回答
  •  余生分开走
    2020-11-29 15:35

    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

提交回复
热议问题