iBeacon - Implementation in iOS

Prekshya Basnet

May 31, 2018

iOS

Beacon technology started buzzing around the year 2013, when Apple first introduced its beacon standard as iBeacon technology. Since then, the use of location based services has escalated in many popular applications such as real estate, restaurants, way finding and many more. I had been hearing about this technology for a year, but never had a hands on experience. So, in this blog, I am sharing all the uncertainties and problems I had faced while implementing beacon for the first time.

The first thing that came to my mind was, “What is a beacon?”. I saw a small device but I really couldn't figure out what to do with it. So after some research, I found that a Beacon is a bluetooth low energy physical device that repeatedly emits a signal which can be received by devices configured to receive it.

The next thing that popped into my mind was, “What information do I get from that signal and how do I recognize a beacon?”. For that we need to dig deeper into iBeacon or Eddystone protocols that our beacons are configured with.

iBeacon is a protocol standardized by Apple that gives three information about beacon: UUID(Unique Universal Identifier), major and minor. UUID gives general information about the beacon such as the company it belongs to. Major gives general spatial information in which region a beacon is located where as minor gives more minute information in which sub-region a beacon belongs to.[1] Eddystone is a protocol developed by Google that works similar to iBeacon with additional features. It provides four pieces of information: UID (Unique ID), URL, TLM(Telemetry) and EID(Ephemeral Identifier). UID provides uniques identification similar to iBeacons (UUID, major and minor), URL is encoded directly into packet, TLM provides telemetry data such as battery voltage and EID is similar to UID but encrypted for additional security purpose. [2]

Taking into consideration the nature of iBeacon and Eddystone protocols we inferred that, iBeacon is perfect for our use case.

Use case: When a user enters a canteen within a region of 15m, the user should be notified about currently available menu.

Solution: Since we had a Kontakt.io beacon, we planned to set up the beacon’s UUID, major and minor values to uniquely identify the canteen. When a user enters the region, the device detects the beacon. From the identified beacon we can know that it is in canteen’s beacon from its UUID, then use its major-minor value to get the current menu from the server. If current menu is available then the user will be notified using a local notification about the menu.

First I installed Kontakt.io SDK, and implemented its delegates necessary to detect beacons. There were a lot of queries and scenarios in my mind, that needed to be tested. Taking into consideration each query and scenario, I resolved them one by one which is listed below:

Question: In what sequence the delegates are called and its individual purposes?

Answer: Delegates to handle are: Region Entered: When user first enters the region, didEnter is called

func beaconManager(_ manager: KTKBeaconManager, didEnter region: KTKBeaconRegion)


Region Exited: When user has left the region, didExitRegionregion is called.

func beaconManager(_ manager: KTKBeaconManager, didExitRegion region: KTKBeaconRegion)


Ranged beacon: After user enters the region we start ranging manually with startRangingBeacons,

startRangingBeacons(in: region)


and then didRangeBeacons is called where we get all beacons identified by the device in that region.

func beaconManager(_ manager: KTKBeaconManager, didRangeBeacons beacons: [CLBeacon], in region: KTKBeaconRegion)


Determined state: didDetermineState is called automatically when user is in the borderline that is, called when user enters a region and also when user exits a region.

func beaconManager(_ manager: KTKBeaconManager, didDetermineState state: CLRegionState, for region: KTKBeaconRegion)


Question: When do we need to start monitoring for the region so that device knows if user has entered the region?
Answer: We cannot start monitoring region unless we have location services authorization. If we need to monitor even when the user is not using the app, we need to allow locationAlwaysAuthorization otherwise locationWhenInUseAuthorization will suffice. Thus, when the user first installs the app, we ask for location services permission and if the user grants the permission we can start monitoring the region. We can however start monitoring the region anytime when the user grants location services permission.

func beaconManager(_ manager: KTKBeaconManager, didChangeLocationAuthorizationStatus status: CLAuthorizationStatus) {
        switch status {
        case .authorizedAlways: startMonitoring(region: region)
        default: break
        }
    }

Question: Does the iOS device detect beacon in background and when app is not running?
Answer: In all scenario foreground, background and when app is terminated, didEnter is always called when user enters a region. So yes, our device detects a beacon region but to detect beacon we need call start ranging every time user enters a region.

Question: Does the iOS device continuously detect beacon in foreground, background and when app is not running?
Answer: For continuous beacon detection, we need to keep ranging and ranging works only in foreground. No, the device does not continuously detect beacon when app is in background and when terminated since ranging is stopped automatically. We will need to work on configuring background modes in iOS if we need continuous update on users location but need approval of App Store for our purpose.

Question: Is region entered called even if user is already inside a region?
Answer: When user is already in region, didEnter region is not called. So how do we detect a beacon? We remove didEnter and didExitRegion and implementdidDetermineState so that, we can manually call didDetermineState to know whether user is already inside region or not and then, it will trigger automatically whenever user exits and enter a region.

Question: Is it possible to send a notification when app is not running or as been terminated?
Answer: On any of the above state our device wakes up for few seconds when user enters a region. Delegates did determine state and did enter state is called. Then we range beacon, get current menu and send notification .

Finally, we were able to implement the beacon in our application suitable for the use case as mentioned above. The only issue that still bugs my mind and has stayed unresolved is what if we needed to continuously range beacons to continue notifying the user whenever a menu is published? For now, we need to just give notification only once when user enters the canteen. This will definitely bring me back for more but for now, working in this implementation was enjoyable and beneficial in learning about beacon and how iOS works with this technology.


Reference:

[1] https://kontakt.io/beacon-basics/ibeacon-and-eddystone

[2] https://developer.estimote.com/eddystone

Related Posts

Unit Testing

Smartmobe Pvt. Ltd

Sep 04, 2018

Android, CMS, iOS, Website

iBeacon - Implementation in iOS

Prekshya Basnet

May 31, 2018

iOS