Beacons are not something new. Apple introduces the iBeacon in 2013 but it is very hard to spot the application which integrates the beacon technology. In July 2015, Google open source the EddyStone project and the real world application inspires us to take another look at the beacons in Android team.

First of all, we bought a few beacons from Sensoro and the beacons support both iBeacon and Eddystone protocols. Let's sort out the relevant technology around the beacons before we dirty our hands with code.

We also bought a few beacon powered by USB which turns out quite useful for development. You cannot power off the battery beacon easily but you can unplug the USB beacon within seconds.

Beacon
A device cannot connect WIFI or GPS and broadcast BLE signal to the nearby mobile phones. Its physical appearance is the key although it may collect extra information like acceleration and temperature. It may last for years with standard AA battery. Uniquely identified by a UUID/device name.

Eddystone
A protocol proposed by Google to standardise the communication between beacons and phones. In other words, it defines what is included in the 10 bytes data broadcasted by the beacon. You can read the specification to find out more.

Proximity API
Google's solution to manage the beacons. A beacon cannot carry too many information since the broadcast signal is publicly available. Google introduces this API as a mapping between a physical beacon and the virtual dataset stored in the remote database so that developer can modify the beacon's attachments via the RESTFUL API.

Nearby API
Google's solution to help the client to get the information attached with the beacon. The API requires Google Play Service running on Android phones and hides the interaction between beacon and phones. With Nearby API, you don't need to care which beacon it is, but the extra information attached with the beacons.

Things are pretty clear now. We decide to build a Android app to control the beacons and a demo application to utilize the beacon.

Bet on Google?

Proximity API depends on RESTFUL API so literally you don't need to work on Google, while Nearby API only with Google Play Service on Android. Google's API package cannot guarantee 100% availability, thus for production apps, we likely implement a similar infrastructure like what Google offers (image source: Google Developer).

google-api-beacons

For naive implementation, we can replace the Proximity Beacon API with a RESTFUL API service backed by a key-value data storage. As we just work on a demo, we choose to stick to Google's solution so that we can fully grab the vision.

Create Management App

We follow the official demo to create the management app. After authentication, we register the beacon to Google via beacons.register. With the beaconName assigned for each beacon, developers can manipulate the "attachment" associated with the beacon.

How to identify the beacon

Scan the bluetooth device via the native Android API and you will find the UID frame broadcast by the beacons.

ScanRecord record = result.getScanRecord();
//EddyStone.EDDYSTONE_SERVICE_UUID = "0000FEAA-0000-1000-8000-00805F9B34FB"
byte[] serviceData = record.getServiceData(EddyStone.EDDYSTONE_SERVICE_UUID);
byte[] beaconId = Arrays.copyOfRange(serviceData, 2, 18);

Great, now you have the beacon ID, proceed to whatever web service to find the identity of this device. In the case of Google Proximity API, you should register this beacon to Google and acquire a beacon name for other API calls.

Manage the data

As mentioned earlier, beacon cannot connect to internet and its physical appearance is all it can offer. Although a basic storage is available on the device, it is more flexible to store extra information on the cloud, hereby you can modify later without getting close to the beacon.

The solution from Google is called "attachment". Each beacon can carry a list of attachments, distinguished by the namespace and stored in bytes. The attachment's namespace gives information on the data types, so you can convert the bytes to string, int, long etc.

Restful API

Google's API is easy to work with. We took a different approach from the demo to construct the Http calls but still stick to Okhttp as the backbone. First all, we define a base class BaseRequest to support PUT/DELETE/ADD/UPDATE.

    public static final String AUTHORIZATION = "Authorization";
    public static final String BEARER = "Bearer ";
    public static final String ENDPOINT = "https://proximitybeacon.googleapis.com/v1beta1/";

    protected Response getJson(String token, String query) throws IOException {
        Request request = new Request.Builder()
                .header(AUTHORIZATION, BEARER + token)
                .url(ENDPOINT + query)
                .get()
                .build();
        return mHttpClient.newCall(request).execute();
    }
}

Then for each API, extend from this base class to handle different kinds of actions, i.e. retrieve all namespaces

public class ListNamespaceRequest extends BaseRequest {

    private String mToken;

    public ListNamespaceRequest(OkHttpClient client, String token) {
        super(client);
        mToken = token;
    }

    @Override
    public String getAPIName() {
        return "";
    }

    Response getResponse() throws IOException{
        return this.getJson(mToken, "namespaces");
    }
}

Create Client App

You must put the client app under the same Google Project as you did with the management app so that they can share the same data (attachment).

Follow the instruction, create a Google API client:

mGoogleApiClient = new GoogleApiClient.Builder(mTransactionActivity.getApplicationContext())
                .addApi(Nearby.MESSAGES_API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Then implement the callback to handle the message.

 mMessageListener = new MessageListener() {

            @Override
            public void onFound(final Message message) {
               //handle the beacon message
            }

            @Override
            public void onLost(Message message) {
               //when beacon is gone
            }
        };

After all, subscribe the updates via callbacks.

SubscribeOptions options = new SubscribeOptions.Builder()
                    .setStrategy(Strategy.BLE_ONLY)
                    .setCallback(new SubscribeCallback() {
                        @Override
                        public void onExpired() {
                            //no longer subscribe
                        }
                    }).build();

Nearby.Messages.subscribe(mGoogleApiClient, mMessageListener, options)
                    .setResultCallback(new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            if (status.isSuccess()) {
                                Logger.i("subscribed successfully!");
                            } else {
                                Logger.i("Could not subscribe!");
                                //resolve the errors
                            }
                        }
                    });

Now you have an Android app which can work with beacons!

Long way to go

One of our app has a very practical use case for beacon. In short, we use the beacon to replace tedious manual input or QR scanning to identify the customer identity. And it works great. However, before we deploy the app into production, a few things to consider from the engineering perspective:

  • build a web-based infrastructure to replace Google's API
  • improve the management tool so that it works with multiple apps
  • build a shared library to work with our own backend service