iOS: CoreLocation Framework and Beacon Detection

Beacon technology is one of the exciting technologies that have enabled location awareness possibilities for apps. Because of the increasing popularity of the technology, iBeacon was introduced, which extends CoreLocation Framework in iOS for beacon detection using monitoring and ranging. The signals from a beacon can now be monitored using any iOS device that supports Bluetooth 4.0.

Using CoreLocation Framework with iBeacon Technology:

To use iBeacon technology for beacon detection, we first need to import CoreLocation and CoreBluetooth into our project and include the header files of these frameworks in our ViewController header file.

#import <CoreLocation/CoreLocation.h>

#import <CoreBluetooth/CoreBluetooth.h>

Once these frameworks are included in the view-controller, we use CLLocationManager class for all the location-related activities. CLLocationManager class is the central point for configuring the delivery of location to our app. These are the main activities related with beacon detection for which support is provided by CLLocationManager class:

  1. Monitoring various regions and notifying whenever the user enters or leave the region.
  2. Reporting the range from nearby beacons.
  3. Deferring the delivery of location updates, even when the app is in background.

Since the above three activities are at the core of beacon detection, active location services are must for a robust application interacting with beacons.

Initialize Location Services: The first thing that we need to do is to initialize location manager and set ourselves as the delegate.

self.locationManager = [[CLLocationManager alloc] init];
self.loacationManager.delegate = self;

Setting distance filter and desired accuracy: Distance filter signifies the minimum distance required before an event is generated and desired accuracy sets the accuracy that we require of an application.

self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;

The other values that desired accuracy variable can have are-

  1. kCLLocationAccuracyBestForNavigation
  2. kCLLocationAccuracyBest
  3. kCLLocationAccuracyNearestTenMeters
  4. kCLLocationAccuracyHundredMeters
  5. kCLLocationAccuracyKilometer
  6. kCLLocationAccuracyThreeKilometers

Setting distance filter as kCLDistanceFilterNone signifies that we want to be notified as many times as possible hence, keeping the distance filter to the minimum.

Setup a Beacon Region:

Beacon region is the area around a beacon that is defined by the device’s proximity to the beacons. The process of detecting beacons by an application can be explained in two steps- Monitoring and Ranging. A beacon region can be defined as follows-

// Create a NSUUID with the same UUID as the broadcasting beacon
    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:UUID];
// Setup a new region with that UUID and same identifier as the broadcasting beacon
    self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:BeaconRegionIdentifier];
// Notify whenever app enters or leaves a beacon region. 
    self.myBeaconRegion.notifyOnEntry = true;
    self.myBeaconRegion.notifyOnExit = true;

Keeping Location Services always active:

Whenever we need our application to continuously track someone’s movement, we require location services to be always active. But, because of heavy battery consumption, iOS kills the app after some time once the app is in background. Although keeping location services constantly active should be avoided (except in the cases when it’s necessary), it can be achieved by following certain steps.

In order to ensure that the app is continuously monitoring and ranging for beacons even when the app is in background (display of the device is still on), we need to set this property to true.

// Notify whenever app enters or leaves a beacon region. 
  self.myBeaconRegion.notifyEntryStateOnDisplay = true;

But, it is noticed that even after this, the application stops ranging for beacons once it is out of all the beacon regions.

// Notify whenever app enters or leaves a beacon region. 
// Tell location manager to start monitoring for the beacon region
    [self.locationManager startMonitoringForRegion:self.myBeaconRegion];
    [self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];

-(void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion *)region
{
	[self.locationManager stopMonitoringForRegion:self.myBeaconRegion];
}

Once the ranging is stopped, it might take 30 seconds to 5 minutes for the app to retain ranging. In order to avoid this, we should make sure that the ranging for beacons is never stopped. In other words, we shouldn’t call

[self.locationManager stopMonitoringForRegion:self.myBeaconRegion];

in didExitRegion location manager delegate.

Apart from that, in order to make sure that iOS doesn’t stop location updates when the app is idle for some time and is in background, we should set this property as false.

self.locationManager.pausesLocationUpdatesAutomatically = false;

Exception in iOS 8:

It is observed that even after following above steps, the location services keep turning off in iOS 8 device. To make sure that the proper beacon detection takes place in iOS 8 devices too, we need to do two extra things –

  1. Add one or both of the below keys to Info.plist file –
    1. NSLocationWhenInUseUsageDescription
    2. NSLocationAlwaysUsageDescription

We also need these before starting location updates. The first one is for location updates in both the foreground and background, and the second one is for foreground location updates only.

    [self.locationManager requestAlwaysAuthorization];
    [self.locationManager requestWhenInUseAuthorization];

If the application supports various iOS versions, the above code snippet should be included only for iOS 8, as it will cause the application to crash for other iOS versions. One method to achieve this is as follows –

    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    {
        [self.locationManager requestAlwaysAuthorization];
    }

Once all this is done, start the location updates by calling this method.

[self.locationManager startUpdatingLocation];

Various delegates called on beacon detection:

-(void) locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *) region 
{
}

 

1. Whenever the app enters a beacon region, this delegate gets called.

2. This delegate is called as soon as the app is outside of all beacon regions.

-(void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion *)region {
}

3. This delegate is called repetitively and gives the proximity of app from beacon and other details about the beacons.

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

Among the above three, the first two events are fired while monitoring for beacons and the third one is fired with beacon regions-ranging.

Sparsh Khandelwal

Sparsh Khandelwal

Software Engineer

Sparsh Khandelwal is a Software Engineer at 3Pillar Global. He has experience in .NET technology and iOS application development in Objective C. Sparsh is a graduate from the renowned Indian Institute of Technology (IIT), Delhi. He is an avid reader and loves to spend his time reading novels.

3 Responses to “iOS: CoreLocation Framework and Beacon Detection”
  1. Ahmed Hamdy on

    // Create a NSUUID with the same UUID as the broadcasting beacon
    I want only collect beacon ,why i use UUID ?

    Reply
    • Sparsh Khandelwal on

      Every beacon can be provided with an UUID and then we mention in the app which UUID to listen to. It helps in avoiding listening to the beacons that aren’t the ones we want to listen to. For e.g., if there are two stores side by side with their own beacons, they don’t want their apps to interact with the beacons of another store.
      Having said that, it’s not possible to listen to beacons with any UUID. It is essential that we provide the app with some UUID.

      Reply
  2. Vivek on

    Hi Sparsh,

    I have a question need to create an attendance marker using beacons.
    1)How can I keep the app running always?(I think its already in your blog)
    2)Do I need any sdk or I can use the iOS APIs directly?
    3)Will the location services security prompt me with Alerts for user permissions, now and then about my app using location services and need users acceptance again and again? Can this be avoided?

    Reply
Leave a Reply

Related Posts

Jessica Hall Presents Webinar on Product Strategy Jessica Hall, 3Pillar's Senior Director of Product Strategy & Design, recently presented a Product Lunch webinar in conjunction with Product Colle...
Take 3, Scene 28 – Do You Have a Productive Product Mi... In Take 3, Scene 28, we talk to Massi Behbahani and Cindy Halim about what they learned at the Mind The Product conference, why empathy matters when w...
Money 20/20 Preview: What We’re Looking Forward to at ... Two 3Pillar team members will be attending Money20/20 in Las Vegas the week of October 23, 2017. Billing itself as the “World's Largest Payments &...
Credit Card Fraud Detection – An Insight Into Machine ... The importance of Machine Learning and Data Science cannot be overstated. If you are interested in studying past trends and training machines to learn...
Robert Malai on How Not to Use Docker at the Rise of the Dev... On June 17th, Robert Malai spoke at the Rise of the DevOps conference in Timisoara, Romania. Rise of the DevOps is a conference aimed at the growth of...

SUBSCRIBE TODAY


Sign up today to receive our monthly product development tips newsletter.