August 18, 2014

Swiftly Speaking: Beacon App Development Using Swift & Bluetooth LE

Much has been written recently about Bluetooth LE, the technology that allows for sensor-based user recognition. Bluetooth LE is the technology that powers Apple’s iBeacon and other beacon technology. Many are hailing it as the savior of industries like retail & advertising.

In the aftermath of Apple’s WWDC 2014, much has also been written about Apple’s new Swift programming language. Swift will replace the Objective C coding language that iOS developers like me have used since the iPhone’s debut in 2007.

I wanted to get my hands dirty with both Swift and Bluetooth LE, so I recently built a prototype that enables a “connected office” concept that allowed me to track the location of designated iPhones and Androids within the 3Pillar office. Creepy? Slightly.

But what if it meant no longer having to track your time or book meetings? That’s just one of the potential use cases we wanted to explore in building this protoype iOS and Android app. I used Swift, Apple’s development environment Xcode, Java for Android, and a NodeJS web service to develop the application. It took about 2 weeks to create and deploy the prototype from start to finish.

This blog post will cover the most important components of the experience – the hardware and the software – and a few lessons about Swift I learned along the way.

The Hardware: What do Beacons look like? And what do they do?

Estimote Beacons

The beacon devices that we used are about 2 inches long and an inch wide. They feel rubbery and have a range of around 200 feet. This meant that I could place them in central locations in our office and have them read selected devices that we had connect to the sensors via Bluetooth LE. We only did this with 3 iPhones and an Android to test the concept. iBeacons are not very expensive. The model we bought were Estimote Beacons, which come in packs of 3 for $99.

For better or for worse, the most frequently cited example of what beacons will eventually enable is targeted advertising tailored to an individual a la Minority Report. It’s not necessarily my role to envision all the potential applications of a technology like iBeacon, but I would like to think that it will enable something greater than the ability to target advertisements more effectively. Here is how Apple talks about iBeacon on their website: “From welcoming people as they arrive at a sporting event to providing information about a nearby museum exhibit, iBeacon opens a new world of possibilities for location awareness, and countless opportunities for interactivity between iOS devices and iBeacon hardware.”

If you’re interested in reading more about iBeacon, you can read Apple’s “Getting Started with iBeacon” guide from June of this year. The video embedded below also shows a potential use case for iBeacon at the Louvre art museum in France.

The Software: What it was like developing an iOS app in Swift

For the most part the development went well. I was able to pick up the syntax of Swift rather quickly, and I built a Swift client to a NodeJS web service I’d created without much trouble.

The one serious issue I had showed up when I deployed the app as an IPA. I had a table view that worked fine if I deployed directly to the device from XCode but showed up blank if I deployed an IPA.

Eventually I worked out that iterating over an AnyObject variable that contains a dictionary (such as the return from JSON deserialization), or directly creating an array from its value without a conditional cast will work when you deploy it with Xcode, but would otherwise fail.

In code:

var json:AnyObject = NSJSONSerialization.JSONObjectWithData("{\"adsfasdf\" : \"Anthony\",\"fej839f34\": \"Caroline\",\"j89d2dj2a\":\"Franciose\",\"g4738r8yef\":\"Wally\"}"
.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false), options: NSJSONReadingOptions(0), error: nil)

var data:Dictionary<String,String> = json as Dictionary<String,String>

var output = “”

// One way of getting all the dictionary values into an array

var ar:[String] = Array(dict.values)

// And another

for (deviceId,name) in data as Dictionary<String,String> {

ar.append(name)

}

for name in ar {

output = output + “\n” + name

}

textView.text = output

Would produce a list in which all of the names in the dictionary were repeated twice if deployed through XCode and would crash when deployed as an IPA. The crash was caused by Array(dict.values). The loop simply produced no results if you left out Array(dict.values). Instead it was necessary to conditionally assign the AnyObject to a dictionary:

if let dict = json as? Dictionary<String,String> {

var output = “”

var ar:[String] = Array(dict.values)

for (deviceId,name) in dict {

ar.append(name)

}

for name in ar {

output = output + “\n” + name

}

textView.text = output

}
Ultimately this is a bug that will likely be ironed out by the time Apple brings Xcode 6 out of beta, but it made for an interesting debugging challenge in developing my first iOS app using Swift.

The End Product: The Application Prototype

iBeacon Apps on iPad and Android

At the end of a few weeks of coding and trial and error, I was able to deploy an application that could reliably tell me which iOS or Android devices were in which conference room. As you can from the screenshots above, the application was not incredibly high fidelity, but that wasn’t the aim from the outset.

The goal was to get hands-on experience working with Swift, beacon technology, and Bluetooth LE, and to see them all in action together so that we have a knowledge base in an area that is certain to see more interest from our clients in the future.