Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run iPhone as an iBeacon in the background

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;     } } } 
like image 738
jpcoder Avatar asked Sep 22 '13 13:09

jpcoder


People also ask

Can an iPhone be an iBeacon?

Overview. Any iOS device that supports sharing data using Bluetooth low energy can be turned into an iBeacon.

Can I use my phone as a beacon?

YES This is possible on Android 5+, and you can find open-source code for transmitting as a beacon in the Android Beacon Library. There is also a full-featured version of a beacon transmitter in the Beacon Scope app in the Google Play Store.

What happened Apple iBeacon?

iBeacon was little more than a footnote during WWDC 2013, and wasn't even mentioned during WWDC 2014. The lack of meaningful support or promotion from Apple certainly didn't help, which may be attributable to the company shifting its developmental focus on near-field communication (NFC), which Apple Pay is built on.

What can you do with iBeacon?

The iBeacon enables smartphones, tablets and other devices to trigger actions when they get in close proximity to a device that transmits iBeacon (commonly those devices are called beacons).


1 Answers

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

like image 85
bentford Avatar answered Oct 25 '22 05:10

bentford