Welcome, NewCircle Customer! ProTech is the new home of all your training needs. Learn More »

Google Proximity Beacons - Part 1

Google recently released the Proximity Beacon API to enable applications to better manage beacon deployments in the field, regardless of the beacon technology they are using. The Beacon API connects deployments using Apple iBeacon, Radius Networks' AltBeacon, and Google Eddystone to a common data store that applications can reference from iOS, Android, and the web. In this article we will explore how to get set up with the Proximity Beacon API, as well as the benefits for using it in your deployments.

You can reference the entire Proximity Beacon Manager sample on GitHub.

The Proximity Beacon API is a set of RESTful endpoints that you can interact with from any platform. There are currently no official client libraries available (although there is a small wrapper nested in Google's Android beacon sample that may help simplify the interactions).

To provide context to the discussion, we will walk through some of the basics involved in creating a manager application for Android to interact with the Proximity Beacon API.

Enabling the API

The Proximity Beacon API is part of the Google Developers Console. You will need to create a new project using a Google account to get started.

Once you have a project created, you need to enable the Proximity Beacon API. This can be done one of two ways. The simplest way is to use this link to enable the API in an existing project (or even create a new one at the same time) if you are already logged in. You can also enable the API manually:

If you go back, Google Proximity Beacon API should now show up under the Enabled APIs tab.

API Credentials

These credentials will not be used in the code, but they are required to bind our manager application's package+signature to the Beacon API project.

In order to manage your beacons, you will need an OAuth 2.0 client ID for each platform where you intend to access the API:

In the console, select APIs & auth → Credentials

First, we need to provide a Product name for the OAuth consent screen. Select the OAuth consent screen tab, fill in that value, and Save.

Select the Credentials tab → Add credentials → OAuth 2.0 client ID. Choose the client that suits your application. In our example, we will be managing the beacons from an Android device, so I chose Android for the Application type. In this case, we need to also supply the SHA-1 of the key used to sign the APK and the application's package name. For other platforms, follow the prompts specific to that type and click Create.

API Key credentials do not work for beacon management features, you must have an OAuth client ID.

These credentials will only be valid for the Google accounts that are editing members of your console project—meaning you must log in with one of the Google accounts listed as an owner or editor in the Permissions section of your console project. Other accounts will not have access to the beacon API methds and will be rejected.

Propagation of these credentials can take a bit of time. After creating your client ID, you may need to wait up to an hour before they will allow clients to access the API. This is especially true for iOS/Android clients.

Authenticating the Client

All requests made of the Proximity Beacon API must be authenticated using an OAuth token generated using the client ID created in the previous step. The simplest method of obtaining an OAuth token from an Android client is to use the GoogleAuthUtil from Google Play Services.

Remember that you (the user) must choose an account that has sufficient access rights in your console project, or none of the API calls will succeed!

This will return back the name (i.e. email address) of the selected account that you can forward to the GoogleAuthUtil to obtain an OAuth client token. This request must include a list of OAuth scopes you want the token to access.

The OAuth scope for the beacon API is https://www.googleapis.com/auth/userlocation.beacon.registry:

The first time you attempt this, it will fail with a UserRecoverableAuthException, because the user hasn't granted your application permission to use their account credentials. The exception provides you with another intent to send the user to a permission screen:

If the user grants access from this dialog, you can safely call getToken() again and it will succeed.

Authenticated Requests

The token you receive must be passed as an Authorization header with each subsequent request to the API. The exact code for doing this depends on your HTTP library of choice, but the following shows how we are doing it in the sample application using Volley:

The beacon database is global, and a given beacon identifier may only be registered once across the entire API (not just your project). If you purchase beacons advertising the default values from the manufacturer, chances are they have already been registered. You will need to change your beacon identifiers to a custom value for your application before attempting to register them.

A beacon can only be registered with the API once, and decommissioned once. A decommissioned beacon identifier cannot be registered again. To take a beacon temporarily out of service, the deactivate action should be used.

The minimum required data for registering a new beacon is the AdvertisedId—which is simply the beacon type (Eddystone, iBeacon, AltBeacon) and the unique identifier broadcast by that beacon— and the initial status (active or inactive). You can see additional fields one can supply to the beacon registration in the API reference:

The beaconName (such as beacons/3!442560da34bd204a9ed7000000003039 from above) will always consist of:

"beacons/" prefix

Beacon type:

1 = iBeacon

3 = Eddystone

5 = AltBeacon

Bang (!) character

Beacon's advertised id as a hex string

Scanning for New Beacons

Using Android as the management platform, we can couple in Bluetooth Low Energy (LE) scanning for active beacon devices that need to be registered. For each observed beacon, the manager application can make a beacons.get request to determine its API status. The API will respond with one of the following:

200 (OK) - Beacon is already registered to your Google console project, and the beacon details are returned in the response.

403 (Forbidden) - Beacon is already registered to a different Google project that you are not authorized to view.

404 (Not Found) - Beacon is not yet registered with the API.

Observed beacons for which the API currently returns a 404 are safe to register with your console project. You can accomplish this by posting the beacon object data (as JSON) in a beacons.register request.

Once we have one or more beacons registered to us, we can list them with beacons.list, and potentially display that list to the user.

Attachment Data

One of the primary constraints with Bluetooth LE is the payload size. Beacon devices send their payload in the advertisement packet, which carries a maximum 31 bytes of data. This provides little headroom to declare much beyond a unique identifier in the advertisement, and places extra burden on the client application to match the discovery of beacons with additional data about the physical site to make the beacon useful.

This is where attachments come in. Attachments allow an additional 1KB of raw textual data to associate with a beacon's advertised unique identifier. The data can be anything that suits your application needs, from a JSON blob to a simple string. For example, if we wanted to attach the following JSON to represent an in-store offer:

Attachment data is always transmitted Base64-encoded to and from the API.

Attachments also include a namespacedType value, which clients can use to differentiate the messages they receive from a particular beacon (more on this later). These type values must be namespaced using the console project name, taking the form {project-name}/{type}.

You can create new attachments and associate them with an existing beacon using beacons.attachments.create. Similar to beacon creation, each attachment has a unique name that is assigned by the API. This value should be blank when creating a new attachment.

After creation, the attachment will be given a name that represents the path to that specific resource:

Retrieve the attachments for a beacon with beacons.attachments.list—which also supports appending the namespacedType query parameter to return a subset of attachments assigned to just that type grouping.

Pros and Cons

Admittedly, this is a lot of setup work to go through to get started observing Google beacons. At first glance, the Proximity Beacon API might seem like unnecessary overhead. While there is setup work involved in gaining access to the API, Google is providing you back-end features you would have likely spent time building yourself anyway for a sufficiently large beacon deployment.

Attachments alone represent a feature almost every beacon deployment needs—the ability to bind additional data to the 31 byte advertisement to make it more contextual for the client application. With the Proximity Beacon API, beacons can be managed such that their role is separate from the hardware advertisements. With a small amount of front-end development, a management console can be created to easily swap out beacons in the field without changing the client-side software's understanding of the data it observes.

On the client side, part of this is leveraging the Nearby Messages API to discover data associated with beacons. In Part 2 of this series, we will look at the client side of the system, and how beacon messages are processed on the user's mobile device.