AltBeacon / altbeacon-transmitter-android

A transmitter app requiring android L
67 stars 32 forks source link

AltBeacon Transmitter

IMPORANT: This project was developed for the first preview release of Android L. The APIs were changed in subsequent updates, so this project does not work with release versions of Android.

This app demonstrates how to use Android L APIs to transmit as a beacon. By default it will transmit an AltBeacon advertisement, but can easily be modified to transmit any other beacon format as well.

If you cannot see the transmission, make sure you have a tool that can detect AltBeacons, like the Android Locate app. Otherwise, change the code to transmit as a different beacon type.

Building the App

You must have an Android L development environment set up with Eclipse, and you must first build and install the android-l-apis branch of the Android Beacon Library in Eclipse as a dependent Android Library project.

A more full-featured version of this app called QuickBeacon is available in the Google Play store here

Getting Google L on your device

Google L is downloadable from Google here.

Key Android L Bluetooth LE Features:

SettingRSSI @1m (iOS)RSSI @1m (Mac)
ADVERTISE_TX_POWER_HIGH -56 dBm -55 dBm
ADVERTISE_TX_POWER_MEDIUM -66 dBm -66 dBm
ADVERTISE_TX_POWER_LOW -75 dBm -70 dBm
ADVERTISE_TX_POWER_ULTRA_LOW (not detected) -79 dBm
Setting Transmit Frequency
ADVERTISE_MODE_LOW_LATENCY approx 1 Hz
ADVERTISE_MODE_BALANCED approx 3 Hz
ADVERTISE_MODE_LOW_POWER approx 10 Hz

UPDATE: The anomaly in thea above settings where ADVERTISE_MODE_LOW_POWER and ADVERTISE_MODE_LOW_LATENCY are reversed has been fixed in release versions of Android 5. The above is accurate only for the preview version of Android L.

Android L API Changes

All these changes are possible because Android now has brand new APIs for interacting with Bluetooth LE under the android.bluetooth.le package documented here. To some extent, these appear to wrap the same Bluedroid drivers under the hood, but the changes are significant. Source code for Nexus device configurations was released a few days ago, but the more important source code for the APIs is still not available, nor is full documentation.

But based on what we can derive from interacting with the the binary preview SDK, a new Java API layer for interacting with bluetooth LE has little resemblance to what was in Android 4.4.3. Some of the hidden APIs needed to transmit as a bluetooth LE peripheral have been moved to the android.bluetooth.le package, and lots of new APIs have been added. The old public APIs are still available, but the new APIs offer much more functionality.

The code needed to transmit as a beacon with Android L’s android.bluetooth.le APIs is a bit different from the way we did it with the android.bluetooth APIs in Android 4.4.3. The first difference to note is that you no longer need the special android.permission.BLUETOOTH_PRIVILEGED permission to transmit an advertisement -- just the standard android.permission.BLUETOOTH_ADMIN permission in your AndroidManifest.xml.

How to set up transmitting

In order to tell Android to transmit a beacon byte sequence, you have to first get an instance of the BluetoothAdapter, and then use the brand new BluetoothLeAdvertiser class which gives you control of advertising.

BluetoothManager bluetoothManager = (BluetoothManager) this.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();      
BluetoothLeAdvertiser bluetoothAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser()

We next need to set the advertisingBytes on the bluetoothAdvertiser. The new APIs still allow you to set both ManufacturerData (which will be sent out with Bluetooth AD type 0xFF) and ServiceData (which will be sent out with Bluetooth AD type 0x16) For the purposes of transmitting as a beacon, we must use the ManufacturerData, because devices looking for beacons expect to see the 0xFF Bluetooth AD type.

AdvertisementData.Builder dataBuilder = new AdvertisementData.Builder();
dataBuilder.setManufacturerData((int) 0, advertisingBytes);

Next we can exercise the additional control Android L gives you over advertising. Both the transmitter power level and the frequency (“advertiseMode”) can be set:

AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);            
settingsBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);         
settingsBuilder.setType(AdvertiseSettings.ADVERTISE_TYPE_NON_CONNECTABLE);

The last step is to start advertising:

bluetoothAdvertiser.startAdvertising(settingsBuilder.build(), dataBuilder.build(), advertiseCallback);

You’ll note that this requires an advertiseCallback definition, which we will define the same way as with Android 4.4.3 like this:

private AdvertiseCallback advertiseCallback = new AdvertiseCallback() {

    @Override
    public void onAdvertiseStart(int result) {
        if (result == BluetoothAdapter.ADVERTISE_CALLBACK_SUCCESS) {
            Log.d(TAG, "started advertising successfully.");                    
        }
        else {
            Log.d(TAG, "did not start advertising successfully");
        }

    }

    @Override
    public void onAdvertiseStop(int result) {
        if (result == BluetoothAdapter.ADVERTISE_CALLBACK_SUCCESS) {
            Log.d(TAG, "stopped advertising successfully");
        }
        else {
            Log.d(TAG, "did not stop advertising successfully");
        }

    }

};