Detecting beacons using Nearby Messages API

My colleagues from iOS are working on a project that is using BLE  beacons to detect when users that have the app installed enter a BLE beacon region. Apple has native support for beacon detection and it seemed pretty straight forward to use on iOS. I was curious how this can be done on Android, and unfortunately it was frustrating, as any other BLE development at the moment of this writing.

On Android one option would be the AltBeacon library which :

Allows Android devices to use beacons much like iOS devices do.

What this library does, is pretty much offers the same API on Android,  as Apple does on iOS. The library is maintained, it has a large user group, but of course there still are problems, and I expect more to come now with the introduction of Doze, and the next release of Android-N, which also brings changes to Doze mode, and power savings.

So I wanted as much as possible a “native” support for this. One option would be to directly use the BLE API like BluetoothLeScanner  and continuously scan in the background for beacons. You would have to probably start the scan at intervals, to not drain the battery, schedule alarms to start the scans, a lot of overhead, I was looking for something more simple. The other option was to use the Nearby Messages API from the Play Services library, which seemed to allow a “background scan mode”.

Integration was not straight forward as I hopped to, some additional steps have to be done and the documentation is not very clear / all over the place. So, in order to integrate “Nearby Messages API” to detect beacons on Android, you will have to do the following :

  1. First create a Google Developer Console project
  2. Enable the “Nearby Messages API” for the project you just created
  3. Create an API Key for this project, as described here and add it to the Manifest
    • <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.google.sample.app" >
          <application ...>
              <meta-data
                  android:name="com.google.android.nearby.messages.API_KEY"
                  android:value="API_KEY" />
              <activity>
              ...
              </activity>
          </application>
      </manifest>
  4. Configure and register your beacons as described here; what I had to do was install the Android app, open it, select the project I just created, discover the beacon and register it with my app
  5. You will have to attach a message to your beacon, to get it detected. I did this using the Beacon Tools app, click the registered beacon, and tap on “Attachments”
  6. Follow the code sample here and it should detect your beacons

For subscribing from an Activity or Fragment you should do the following :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Nearby.MESSAGES_API)
            .enableAutoManage(this, this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    googleApiClient.connect();
}

@Override
protected void onStop() {
    super.onStop();
    googleApiClient.disconnect();
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    Nearby.Messages.subscribe(googleApiClient, new MessageListener() {
        @Override
        public void onFound(Message message) {
            Log.i(TAG, "Found message : " + message);
        }
    });
}

If you want to subscribe in the background, you should pass a PendingIntent instead of a MessageListener :

private void backgroundSubscribe() {
    Nearby.Messages.subscribe(googleApiClient, getPendingIntent(),
            new SubscribeOptions.Builder()
                    .setStrategy(Strategy.BLE_ONLY)
                    .build());
}

private PendingIntent getPendingIntent() {
    return PendingIntent.getService(
             this, 0,
             new Intent(this, BackgroundSubscribeIntentService.class),
             PendingIntent.FLAG_UPDATE_CURRENT);
}

Note: the last method, used to subscribe in the background has a lower reliability, as mentioned in the docs :

Subscribes for published messages from nearby devices in a persistent and low-power manner. This uses less battery, but will have higher latency and lower reliability (notably, updates may only be delivered when the device’s screen is turned on). The subscription will be retained after the client disconnects.

The full source for my sample project where I also handle  the user consent flow, granting permissions, and all the necessary stuff to scan for beacons is available on GitHub .

Advertisements

About Ovidiu

Passionate Android Developer. What else? Snowboarding. Football. Stuff like that.
This entry was posted in Android, BLE, Google, PlayServices and tagged , , , , , , , . Bookmark the permalink.

3 Responses to Detecting beacons using Nearby Messages API

  1. Aaron says:

    Good tutorial.

    I’m trying to detect any beacon using the Nearby api and I’m having problems.
    It seems that I don’t have the right filter so my app can detect any. I’ve been googling for days looking for some way to detect all beacons.

    I know it’s possible because there is an app that does it. The nRF Connect app for android can find my beacons and show their info without the beacons being registered with Google. The app shows the Ibeacon, Eddystone and Physical web data.

    The google docs leave out a lot of info. There is nothing that shows how to detect any beacon or even a specific company’s UUID.

    I would like to be able to detect any beacon and get it’s info without fussing with registering my beacons. I would appreciate any tips.

    I would even take an explanation how to detect any eddystone beacon or Ibeacon or physical web beacon.

    Thanks in advance.

    • Ovidiu says:

      Yeah, for that I think you will have to use the mentioned library : https://github.com/AltBeacon/android-beacon-library .

      I did not get the time yet to write a post about how you can detect beacons with the altbeacon library, but you will have to know the “beacon layout” and pass it to this library in order to get detected. some trial and error might be required, but you’ll get it in the end…

      Good luck.

  2. Aaron says:

    If I can’t do what I want with Google’s Nearby Api, I will check out Altbeacon. I was going to check that out when attempts at using google’s api fail.

    I’m going to post a question on StackOverflow and see what happens.

    I’m guessing that I just need to know how to set up a message filter that accepts all beacons.

    Thanks for your fast reply.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s