Beacon Implementation in Android

06 / Aug / 2015 by Upasana Chauhan 0 comments

In our previous post we have given a overview of what Beacon is, so here we are with its practical implementation.

There are two applications required to create Beacon experience.

1. Transmitter
2. Receiver

For Transmitter –

1. Bluetooth should be on
getSystemService(Context.BLUETOOTH_SERVICE)

2. BLE supported device
hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))

<uses-permission android:name=”android.permission.BLUETOOTH” />
<uses-permission android:name=”android.permission.BLUETOOTH_ADMIN” />

If device supports BLE, then the Beacon Transmitter transmits the advertisements like this,

/**
* Simulates a new beacon every 10 seconds until it runs out of new ones to add.
*/

Beacon beacon = new Beacon.Builder()
       .setId1(“2f234454-cf6d-4a0f-adf2-f4911ba9ffa6”)
       .setId2(“1”)
        .setId3(“2”)
        .setManufacturer(0x0118)
        .setTxPower(-59)
        .setDataFields(Arrays.asList(new Long[] {0l}))
        .build();
BeaconParser beaconParser = new BeaconParser()
        .setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser);
beaconTransmitter.startAdvertising(beacon);
scheduleTaskExecutor= Executors.newScheduledThreadPool(5);
// This schedules an beacon to appear every 10 seconds:
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable(){
         public void run() {
                          try{
                              //putting a single beacon back into the beacons list.
                              if (finalBeacons.size() > beacons.size())
                                  beacons.add(finalBeacons.get(beacons.size()));
                              else
                                  scheduleTaskExecutor.shutdown();
                          }catch(Exception e){
                               e.printStackTrace();
                        }
                  }
            }, 0, 10, TimeUnit.SECONDS);
       }
 }

Beacon Advertisement Receiver

Two classes are main in this receiver
1. Beacon Parser
2. Beacon Manager

Beacon Parser – It parses the advertised data into relevant information.

 

@TargetApi(5)
protected Beacon fromScanData(byte[] scanData, int rssi, BluetoothDevice device, Beacon beacon) {
int startByte = 2;
boolean patternFound = false;
byte[] typeCodeBytes = longToByteArray(getMatchingBeaconTypeCode(), mMatchingBeaconTypeCodeEndOffset-mMatchingBeaconTypeCodeStartOffset+1);

while (startByte <= 5) {
      if (byteArraysMatch(scanData, startByte+mMatchingBeaconTypeCodeStartOffset, typeCodeBytes, 0)) {
              patternFound = true;
              break;
      }
      startByte++;
}

if (patternFound == false) {
       // This is not an beacon
       BeaconManager.logDebug(TAG, "This is not a matching Beacon advertisement.  (Was expecting "+byteArrayToString(typeCodeBytes)+".  The bytes I see are: "+bytesToHex(scanData));
           return null;
}
else {
//BeaconManager.logDebug(TAG, "This is a recognized beacon advertisement -- "+String.format("%04x", getMatchingBeaconTypeCode())+" seen");
Log.e("rec beacon**", "This is a recognized beacon advertisement -- "+String.format("%04x", getMatchingBeaconTypeCode())+" seen");
}

ArrayList<Identifier> identifiers = new ArrayList<Identifier>();
for (int i = 0; i < mIdentifierEndOffsets.size(); i++) {
    String idString = byteArrayToFormattedString(scanData, mIdentifierStartOffsets.get(i)+startByte, mIdentifierEndOffsets.get(i)+startByte, mIdentifierLittleEndianFlags.get(i));
    Log.e("idString",idString);
    identifiers.add(Identifier.parse(idString));
}
ArrayList<Long> dataFields = new ArrayList<Long>();
for (int i = 0; i < mDataEndOffsets.size(); i++) {
     String dataString = byteArrayToFormattedString(scanData, mDataStartOffsets.get(i)+startByte, mDataEndOffsets.get(i)+startByte, mDataLittleEndianFlags.get(i));
     dataFields.add(Long.parseLong(dataString));
     BeaconManager.logDebug(TAG, "parsing found data field "+i);
     // TODO: error handling needed here on the parse
}

int txPower = 0;
String powerString = byteArrayToFormattedString(scanData, mPowerStartOffset+startByte, mPowerEndOffset+startByte, false);
txPower = Integer.parseInt(powerString);

// make sure it is a signed integer
if (txPower > 127) {
    txPower -= 256;
}
Log.e("txPower data",txPower+"");
      
// TODO: error handling needed on the parse

int beaconTypeCode = 0;
String beaconTypeString = byteArrayToFormattedString(scanData, mMatchingBeaconTypeCodeStartOffset+startByte, mMatchingBeaconTypeCodeEndOffset+startByte, false);
beaconTypeCode = Integer.parseInt(beaconTypeString);
// TODO: error handling needed on the parse

int manufacturer = 0;
String manufacturerString = byteArrayToFormattedString(scanData, startByte, startByte+1, true);
manufacturer = Integer.parseInt(manufacturerString);

String macAddress = null;
String name = null;
if (device != null) {
    macAddress = device.getAddress();
    name = device.getName();
}
beacon.mIdentifiers = identifiers;
beacon.mDataFields = dataFields;
beacon.mTxPower = txPower;
beacon.mRssi = rssi;
beacon.mBeaconTypeCode = beaconTypeCode;
beacon.mBluetoothAddress = macAddress;
beacon.mBluetoothName= name;
beacon.mManufacturer = manufacturer;
return beacon;
}

Beacon Manager – It specifies the time interval for scanning Beacons in range.

public static final long DEFAULT_FOREGROUND_SCAN_PERIOD = 1000;
/**
* The default duration in milliseconds spent not scanning between each bluetooth scan       cycle
*/

 

public static final long DEFAULT_FOREGROUND_BETWEEN_SCAN_PERIOD = 2*60*1000;                                 // 2 minutes in foreground

/**
* The default duration in milliseconds of the bluetooth scan cycle when no     ranging/monitoring clients
*/    are in the foreground

public static final long DEFAULT_BACKGROUND_SCAN_PERIOD = 10000;

/**
* The default duration in milliseconds spent not scanning between each bluetooth scan     cycle when no   */    ranging/monitoring clients are in the foreground

public static final long DEFAULT_BACKGROUND_BETWEEN_SCAN_PERIOD = 2*60*1000;                                // 2 minutes in background

Beacon whitepaper dwnload banner

Tag -

bluetooth
FOUND THIS USEFUL? SHARE IT

Leave a comment -