iOS 7 - Beacons

One of the many cool features introduced into iOS 7 is the concept of Beacons. The idea behind them is that you can have an iOS device or even a stand alone device broadcast a beacon. And then within an iOS 7 application you can listen for that beacon and determine if you're within range. If so, then you can display contextual information to your end user. 

For example, MLB is supposedly going to use this technology in their stadiums to provide directions to your seats or even provide your coupons/deals. 

Pretty cool, right? If i've peaked your interest, read on and I'll explain exactly how to add this to your own application. You may be surprised how little code is necessary!

So the first thing you need to do is add the following frameworks to your project:

  • CoreLocation.framework
  • CoreBluetooth.framework
The bluetooth framework is actually only necessary if you plan on using your app to host a beacon. 

Step 1:

First we need to generate a UUID (Universally Unique Identifier). This identifier will be used by both the beacon and your app, so that they can identify each other and establish a connection. 

There are 2 ways to do this. 

  1. Use the uuidgen command-line tool that comes with Xcode. 
  2. Just write some code to generate one. Specifically just use the following method. And then store if off for use in your app. [NSUUID UUID]

Step 2:

Now that you have your UUID, you can create an instance of your region:

NSUUID* uuid = [[NSUUID alloc]initWithUUIDString:@"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"]; 

_region = [[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier:@"myApp"];

The first line creates an instance of your UUID. (Note: you need to replace the string above with your actual UUID, otherwise the uuid returned will be nil)

The next line creates your region. You must pass in a valid UUID and an identifier. The identifier can be any string, but you should make it useful. Especially if your app will handle multiple regions. For example, imagine you were writing an app for a Mall. You could have a region for each store in the mall. So in this case, your identifier would be a unique string that identifies a particular store. 

Step 3:

For this step, lets pretend we're already setup a beacon. Whether it be another iOS device or an independent bluetooth transmitter. And our app wants to listen for that beacon. Assuming that beacon is broadcasting using our same UUUID, we just need to use the following code:

_lm = [[CLLocationManager alloc]init];

_lm.delegate = self;

[_lm startRangingBeaconsInRegion:_region];

We first create a Location Manager, assign its delegate and finally call "startRangingBeaconsInRegion:" That last part tells the app that it should start listening for our specific region that we created in Step 2.

The delegate we assigned if of type: CLLocationManagerDelegate and we just need to listen to one particular method:

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region

{

}

Once we've entered within the beacon's range, this method will fire constantly, providing us all the beacons within our range. You can then loop through each beacon that was returned and determine:

  • It's accuracy in meters
  • It's signal strength
  • And finally it's proximity (Far, Near, Immediate)
You can then use this information in your app, to figure out what you want to display to the user. For example, if we use the mall example we used before, you could determine which store your'e in front of, and then provide the user with coupons or promote new items for sale. 

Step 4

This next step is optional. I'll show you how to make your app become an iOS 7 beacon. (Note: this is why we needed to add the CoreBluetooth.framework)

In order to do this, we first need to create a Peripheral Manager:

_pm = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];

The manager takes 2 parameters. The first is the delegate of type CBPeripheralManagerDelegate and the next is the thread in which it should run on. (We pass in nil so that it runs on the main thread.) 

For the delegate, we only have to implement one method. This method lets us know when the manager has been "powered on".

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral

{

    if(peripheral.state ==  CBPeripheralManagerStatePoweredOn)

    {

        NSDictionary* values = [_region peripheralDataWithMeasuredPower:nil];

        [peripheral startAdvertising:values];

    }

}

Once we know we're on, we can use our region, the same region we created in Step 2, too start advertising our beacon. 

And just like that, you've created a working beacon!

Enjoy!

By Stephen Zaharuk (SteveZ)


Tags / ,