Thursday, October 30, 2014

Sample Code in Android to read any iBeacon PDU

I have created a sample code to read iBeacon PDU in Android.

I will not go into details of how iBeacon PDU look like. You can find a lot of blogs, StackOverFlow posts regarding the same.


This code is inspired from Bluetooth Application Accelerator available at the Bluetooth SIG website

Please do a code review and share your comments/feedback.

You can get complete source code at my GitHub repository here.

First create a simple Beacon class that will hold all elements of iBeacon.


package com.boskysoft.beaconscanner.modal;
/**
* @author bosky
*
* This is a sample modal class for iBeacon
*
*/
public class Beacon {
private final String proximityUUID;
private final String name;
private final String macAddress;
private final int major;
private final int minor;
private final int measuredPower;
private final int rssi;

public Beacon(String proximityUUID, String name, String macAddress,
int major, int minor, int measuredPower, int rssi) {
this.proximityUUID = proximityUUID;
this.name = name;
this.macAddress = macAddress;
this.major = major;
this.minor = minor;
this.measuredPower = measuredPower;
this.rssi = rssi;
}

public String getProximityUUID() {
return proximityUUID;
}

public String getName() {
return name;
}

public String getMacAddress() {
return macAddress;
}

public int getMajor() {
return major;
}

public int getMinor() {
return minor;
}

public int getMeasuredPower() {
return measuredPower;
}

public int getRssi() {
return rssi;
}

}

} 
 


Next, in MainActivity.java declare, 

private BleWrapper mBleWrapper = null;
 

Initialize mBleWrapper

mBleWrapper = new BleWrapper(this, new BleWrapperUiCallbacks.Null() {
@Override
public void uiDeviceFound(final BluetoothDevice device, final int rssi, final byte[] record) {
handleFoundDevice(device, rssi, record);
}
}); 

In handleFoundDevice, capture scanRecord byte array and parse:
 
protected void handleFoundDevice(BluetoothDevice device, int rssi,
byte[] scanRecord) {
String scanRecordAsHex = HashCode.fromBytes(scanRecord)
.toString();
for (int i = 0; i < scanRecord.length; i++) {
int payloadLength = unsignedByteToInt(scanRecord[i]);
if ((payloadLength == 0) || (i + 1 >= scanRecord.length)) {
break;
}
if (unsignedByteToInt(scanRecord[(i + 1)]) != 255) {
i += payloadLength;
} else {
if (payloadLength == 26) {
if ((unsignedByteToInt(scanRecord[(i + 2)]) == 76)
&& (unsignedByteToInt(scanRecord[(i + 3)]) == 0)
&& (unsignedByteToInt(scanRecord[(i + 4)]) == 2)
&& (unsignedByteToInt(scanRecord[(i + 5)]) == 21)) {
String proximityUUID = String.format(
"%s-%s-%s-%s-%s",
new Object[] {
scanRecordAsHex.substring(18,
26),
scanRecordAsHex.substring(26,
30),
scanRecordAsHex.substring(30,
34),
scanRecordAsHex.substring(34,
38),
scanRecordAsHex.substring(38,
50) });
int major = unsignedByteToInt(scanRecord[(i + 22)])
* 256
+ unsignedByteToInt(scanRecord[(i + 23)]);
int minor = unsignedByteToInt(scanRecord[(i + 24)])
* 256
+ unsignedByteToInt(scanRecord[(i + 25)]);
int measuredPower = scanRecord[(i + 26)];
String msg = "uiDeviceFound: "
+ device.getName() + ", rssi:" + rssi
+ ", Mac Address:"
+ device.getAddress()
+ " PROXIMITYUUID:" + proximityUUID
+ " MAJOR:" + major + " MINOR:" + minor
+ " MEASURED POWER:" + measuredPower;
Log.d(LOGTAG, msg);
// use myBeacon as per your need
Beacon myBeacon = new Beacon(proximityUUID,
device.getName(), device.getAddress(), major,
minor, measuredPower, rssi);
}
}
}
}
}
 
// use myBeacon as per your need
Beacon myBeacon = new Beacon(proximityUUID,
device.getName(), device.getAddress(), major,
minor, measuredPower, rssi); 
 

No comments:

Post a Comment