Estimote Proximity SDK for Android Things

Android Things is a version of the Android operating system dedicated for building Internet of Things (IoT) devices.
Because it is still Android, you can use our lovely Proximity SDK to enhance your app with context-aware interactions.

What’s ahead (aka Table of Contents)


Set up your Android Things platform

First of all, you need to have your Android Things OS installed on your prototyping board.
Everything is described in the official Android Things docs, so you need to spend a while and follow the tutorial there.

Once you have your OS installed and internet connection established (either through the ethernet cable, or WiFi),
you can proceed and build your very first beacon-powered app for Android Things.

Create an Android Things project in Android Studio

Go to your Android Studio, and create a new project. If you are using Android Studio version 3.0 or higher, you should be able to create an Android Things project out of the box. Otherwise, follow this guide to discover how to prepare your app to be able to run on Android Things.

Add Proximity SDK to your project

You will obviously need to import our SDK to your project. Add this line to your build.gradle file under dependencies:

  implementation 'com.estimote:proximity-sdk:{INSERT THE CURRENT VERSION HERE}'

Tip: If you are using Gradle version < 3.0.0, then you should use compile instead of implementation. See the difference here.

Preconditions for using BLE scanning on your Android Things board

In order to make your Bluetooth Low Energy scan work properly, there are some requirements your app needs to fulfil.

  1. Your app needs to have Location permission granted. This is already requested by our SDK, but in order for it to work, your app will be granted these permissions
    after the device reboots. Why? Read more here!.
  2. Your device needs to have bluetooth enabled. You can do it programmatically by calling bluetoothAdapter.enable(). Read more here.

Also, if you want, you can use our RequirementsWizard that will help you deal with Bluetooth enabling, permission requesting, and all requirements that need to be fulfilled in order for the BLE scan to work on your board.
Just add an additional dependency on our handy Mustard library:

  implementation 'com.estimote:mustard:0.2.0'

Then, before starting your scan, just use the code below:

           onRequirementsFulfilled = { /* Start your scanning here */ },
           onRequirementsMissing = { /* Handle missing requirements */ },
           onError = { /* Handle any error here */ })

Building an app based on Proximity

You can easily introduce proximity-based experience to your Android Things app. The good news are - it is done in the same way as in your typical Android app.
Read the tutorial here to discover how to add attachments to your beacons, and how to invoke actions inside different zones of your beacons.

Building an app based on beacon sensors data

The most fascinating part of using our Proximity SDK with your Android Things app is that you can consume the data from beacon sensors and create actions based on that data.
For this case our ProximityObserver won’t work - it only allows you to handle proximity-related use cases. For getting sensors data, we have to go deeper (one abstraction level below),
and use the BluetoothScanner to get the stream of packets with the data advertised by your beacons. As we know, beacons are able to advertise many packets of different protocols

  • such as iBeacon, Eddystone, or Estimote Location. For getting sensors data, we need to scan for Estimote Telemetry packets. It’s really simple to setup our BluetoothScanner:

Here is how to do it in Kotlin:

val scanner = EstimoteBluetoothScannerFactory(applicationContext)
val scanHandler = scanner.estimoteTelemetryFullScan()
                    .withOnPacketFoundAction { telemetryPacket ->
                    /* Do something here with the received telemetry packet */ }  

Here is how to do it in Java:

BluetoothScanner scanner =
    new EstimoteBluetoothScannerFactory(applicationContext).getSimpleScanner();
BluetoothScanner.ScanHandler scanHandler = scanner.estimoteTelemetryFullScan()
   .withOnPacketFoundAction(new Function1<EstimoteTelemetryFull, Unit>() {
     public Unit invoke(EstimoteTelemetryFull estimoteTelemetryFull) {
       /* Do something with the received telemetry packet here */
       return null;

You can also choose .withLowLatencyPowerMode(), or .withLowPowerMode(), instead of .withBalancedPowerMode(), but this is up to you.
To stop your scan you need to call the stop() method on your scanHandler object that is returned by the start() method.

Tip: In fact, the Estimote Telemetry packet is so packed with data, that we had to split it up into two separate packets frame A and frame B.
The method above is already joining those frames together for you, but the resulting packet may be reported slightly slower than individual frames.
If you want to get the data for each frame instantly, you can use scanner.estimoteTelemetryFrameAScan() or scanner.estimoteTelemetryFrameBScan().
Also bear in mind, that each individual frame contains only the short beacon identifier. It should still be an unique identifier,
but if you want to use our cloud features (checking the colour of a beacon for example), you should consider using scanner.estimoteTelemetryFullScan() which provides you with the full identifier.
Read more about the Estimote Telemetry frames specification here.

Example app

You can always download our example app and get familiar with its source code!

Known issues

As for DP 6.1 version of Android Things, there were some problems with Bluetooth scanning on Raspberry Pi 3.0, especially when used in noisy environment (lots of beacons, many Wi-Fi networks, etc.).
There were no such problems with NXP i.MX7D. Bear in mind that this is still a Developer Preview of Android Things OS, so these problems may be fixed in future releases.