By James Nebeker

Developing Cross-platform Beacon Enabled Apps With PhoneGap/Cordova and Proximity Kit

PhoneGap and its open source counterpart, Cordova, are powerful tools for easily developing mobile apps for multiple platforms. Rather than having to build and maintain separate projects for different operating systems, you can concentrate on a single project and let PhoneGap/Cordova build the native iOS/Android code almost instantly. With the extensive integration with native components (e.g., camera, device motion) it’s easy to seamlessly build Cordova/PhoneGap apps that appear identical to native apps without having to learn a snippet of native code. It was with this in mind that we developed the Proximity Kit Cordova Plugin, which brings Proximity Kit’s powerful location features to the PhoneGap/Cordova platform. With the plugin it’s easy to add proximity beacon capabilities to your project, and it works with both iOS and Android. This post will outline the steps needed to add the Proximity Kit Plugin to your PhoneGap/Cordova project and get you up and running with beacon enabled apps in no time.

Getting Started With Proximity Kit

First things first, you’ll need to make sure you sign up for Proximity Kit (it’s free) and create your first kit. If you haven’t already, go to the Proximity Kit page and create an account, then go to your kits page and create your first kit. Add at least one beacon to your kit, you can choose any identifiers you’d like but you will need a way to transmit those identifiers later on when testing your app (either with beacon hardware or with another mobile device that has BLE transmit capabilities). Once your kit is set up, download its config files for Android and iOS (the download links are on the left side of the kit page) and stash them in a safe place for later.

Installing the Plugin

From here on out I’m going to assume you’re developing with Cordova to avoid having to write each command twice. But have no fear, all of these steps will work just the same if you’re using PhoneGap. I’ll also assume you already have a Cordova project set up, if not you can also clone the reference project for the plugin or start from scratch by running the cordova create command:

$ cordova create hello com.example.hello HelloWorld

The Proximity Kit Plugin is distributed via Github, to add it to your Cordova project run the following command:

$ cordova plugin add https://github.com/RadiusNetworks/proximitykit-plugin-cordova

This will add the plugin to your project’s config.xml file and will copy various files into the native src directory for your platforms.

For this demo we’ll also need the Cordova console plugin so we might as well install that now:

$ cordova plugin add org.apache.cordova.console

Now that the Proximity Kit plugin is installed we can start to incorporate it into your project’s JavaScript.

Triggering Beacon Events in Your Cordova App

After adding the Proximity Kit plugin to your project, there is no need to explicitly require any Proximity Kit JavaScript files in your own code. The plugin manifests itself in JavaScript as radiusnetworks.plugins.proximitykit. There are two methods on this object: watchProximity and clearWatch. The first, watchProximity, takes two handler functions upon initialization and returns a watchId as a way to cancel Proximity Kit callbacks later if desired (using the clearWatch method). The first handler, successHandler, is a function that receives a message object from Proximity Kit on a periodic basis. The message object always has an eventType associated with it, stored as a String. The second handler function, failureHandler, is a function that receives a message containing the failure message as a String. To see a full list of the different Proximity Kit event types and the data associated with these events, check out the plugin’s README on GitHub.

To start receiving Proximity Kit event callbacks, we just need to set up the two handler functions in your project’s index.js file and then call watchProximity in the app function of the same file. To keep things simple for this demo we’ll just set up the handlers to log the event, here’s what the JavaScript for the two handlers will look like:

var proximityKitSuccessHandler = function(message) {
    // Obtain event type from message object
    var pkEventType = message[radiusnetworks.plugins.proximitykit.constants.keys.eventType];
    var beacon = null;
    // Log beacon information if receiving a ranging callback
    if (pkEventType == radiusnetworks.plugins.proximitykit.constants.eventTypes.rangedBeacon) {
      beacon = message[radiusnetworks.plugins.proximitykit.constants.keys.beacon];
      if (beacon != null) {
        console.log("Proximity Kit Event: " + pkEventType + " " + JSON.stringify(beacon));
      }
    }
    // Log event type if receiving another type of callback
    else {
      console.log("Proximity Kit Event: " + pkEventType);
    }
};
var proximityKitFailureHandler = function(message) {
    console.log("Failure: Response from plugin is " + message);
};

Now just add the watchProximity call inside onDeviceReady and that’s it, you’re ready to build the project:

onDeviceReady: function() {
    watchId = radiusnetworks.plugins.proximitykit.watchProximity(proximityKitSuccessHandler, proximityKitFailureHandler);
},

Integrating Proximity Kit

If you haven’t already, add the desired platforms to your Cordova project:

$ cordova platform add android
$ cordova platform add ios

Next, remember those config files we downloaded earlier when setting up our kit on Proximity Kit? You should have a ProximityKit.plist file (for iOS) and a ProximityKit.properties file (for Android). Copy these files into the following locations depending on your platform:

PlatformLocation of Proximity Kit configuration fileiOS./platforms/ios/Your App’s Name/ProximityKit.plistAndroid./platforms/android/src/ProximityKit.properties

Now there are a couple more steps for each platform to add Proximity Kit dependencies to the app.

iOS

In addition to placing the ProximityKit.plist file inside the iOS project’s directory structure, you need to add the file to the Xcode project and to the appropriate target:

  1. Open the project in Xcode (platforms/ios/Your App’s Name.xcodeproj)

  2. Select your app’s target and select “Add Files to ‘Your App’s Name’” from the File menu.

  3. Locate your ProximityKit.plist file and click “Add”

For iOS, Proximity Kit uses SQLite internally so you need to link to it in the project in Xcode manually after the app is built in Cordova/PhoneGap.

  1. Select the App’s target in Xcode

  2. Choose “Build Phases”

  3. Under the “Link Binary With Libraries” section click the ‘+’ to add another library

  4. Choose libsqlite3.dylib and click “Add”

Lastly, in order to use Location Services you will need to add a ‘NSLocationAlwaysUsageDescription’ string to the ‘Info.plist’ file in your iOS app. Without this, your device will not send beacon information to your app. The screenshot below shows an example of this:

Android

To allow background triggering of beacon events on Android the plugin has a custom application subclass (which can’t be setup automatically by Cordova). To implement this in the app edit the AndroidManifest.xml file (platforms/android/AndroidManifest.xml) to include the proper android:name tag under application for the ProximityKitCordovaAppication class. For example, here is the application header for the Proximity Kit plugin reference app:

<application android:name="com.radiusnetworks.cordova.proximitykit.ProximityKitCordovaApplication" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">

Running the App

Note: You need to run your app on a Bluetooth LE-enabled device in order to detect beacons, Android and iOS emulators currently do not have the ability to test beacon functionality.

Running From the Command Line

To build, install, and run the app on your Android device, execute the following command in the project directory:

$ cordova run --device android

Similarly for iOS:

$ cordova run --device ios

Note that running the app from the command line for iOS can be extremely slow. Running the app from Xcode for iOS is recommended.

Running From Xcode

  1. Open the following project in Xcode if you have not already done so.

  2. Select the “Hello Beacon” scheme and your iOS device.

  3. Run the app by choosing “Run” from the “Product” menu.

Testing With a Beacon

Now that the app is up and running, fire up a beacon that matches the identifiers you configured in your kit. You should see the Proximity Kit events being logged in the debug console. Note that on Android your device will only be able to detect beacons following the AltBeacon specification by default. If you wish to detect other proprietary beacons on Android, you can set a BeaconParser supplying the proprietary beacon format (you can search Google for BeaconParser formats) in the onCreate method inside the ‘ProximityKitCordovaApplication.java’ file located in the Android app source code:

@Override
public void onCreate()
{
  super.onCreate();
  Log.d(TAG, "onCreate");
  pkManager = ProximityKitManager.getInstanceForApplication(this);
  pkManager.setProximityKitSyncNotifier(this);
  pkManager.setProximityKitMonitorNotifier(this);
  pkManager.setProximityKitRangeNotifier(this);
  pkManager.getBeaconManager().setDebug(true);
  // Replace the beaconLayoutString with your custom format and uncomment the two lines below
  //String beaconLayoutString = "m:2-3=BEAC,i:4-19,i:20-21,i:22-23,p:24-24";
  //pkManager.getBeaconManager().getBeaconParsers().add(new BeaconParser().setBeaconLayout(beaconLayoutString));
  pkManager.start();
}

You’ll also need to import BeaconParser at the top of ‘ProximityKitCordovaApplication.java’:

import org.altbeacon.beacon.BeaconParser;

Now you’ve successfully built a beacon-enabled Cordova/PhoneGap app!

What’s Next?

Now that you’re receiving Proximity Kit callbacks in your app’s JavaScript, you’re ready to build an awesome app that can trigger content or notifications based on proximity (and works seamlessly on both Android and iOS). Be sure to checkout the Proximity Kit plugin’s README for the complete list of event types and their associated data. If you have any questions or comments drop us a line at support@radiusnetworks.com.