/AndroidIBeaconDemo

Implement Apple IBeacon on Android

Primary LanguageJavaMIT LicenseMIT

AndroidIBeaconDemo

Implement Apple IBeacon on Android

背景资料

这里详细介绍了iBeacon协议中的关键字段,此Demo根据协议中的字段,将蓝牙扫描到的记录字段做解析,判断记录是否是iBeacon包,并获得iBeacon中的信息字段,包括UUID,major,minor,txpower。

02 # Number of bytes that follow in first AD structure

01 # Flags AD type

1A # Flags value 0x1A = 000011010

bit 0 (OFF) LE Limited Discoverable Mode

bit 1 (ON) LE General Discoverable Mode

bit 2 (OFF) BR/EDR Not Supported

bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)

bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)

1A # Number of bytes that follow in second (and last) AD structure

FF # Manufacturer specific data AD type

4C 00 # Company identifier code (0x004C == Apple)

02 # Byte 0 of iBeacon advertisement indicator

15 # Byte 1 of iBeacon advertisement indicator

e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon proximity uuid

00 00 # major

00 00 # minor

c5 # The 2's complement of the calibrated Tx Power

关键实现步骤

通过BluetoothAdapter启动低功耗蓝牙的扫描,指定LeScanCallBack作为参数处理接收到的记录,这部分操作在IBeaconMonitorService.java中。

// start le scan
boolean isScanStarted = getBluetoothAdapter().startLeScan(leScanCallBack);
private BluetoothAdapter.LeScanCallback leScanCallBack = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
    // 这里的scanRecord就是要处理的记录
    }
}

处理接收到的记录,这是一个byte数组,根据协议规定判断是否是iBeacon包,再取出相应位置的字段获取信息,这部分代码在IBeacon.java中,

public IBeacon readFromArray(byte[] src) {
	// see
	// http://stackoverflow.com/questions/18906988/what-is-the-ibeacon-bluetooth-profile
	Log.v(TAG, this.bytesToHexString(src));

	if (((int) (src[7] & 0xff) | ((int) (src[8] & 0xff)) << 8) != 0x1502) {
		Log.d(TAG, "this is not ibeacon !");
		return this;
	}

	Log.d(TAG, "find ibeacon !");

	// read uuid
	byte[] arrayUuid = new byte[16];
	System.arraycopy(src, 9, arrayUuid, 0, 16);
	Log.i(TAG, "uuid - " + this.bytesToHexString(arrayUuid));
	this.uuid = this.bytesToHexString(arrayUuid);

	// read major
	this.major = (int) (src[25] & 0xff) | ((int) (src[26] & 0xff)) << 8;
	Log.i(TAG, "major - " + Integer.toHexString(major));

	// read minor
	this.minor = (int) (src[27] & 0xff) | ((int) (src[28] & 0xff)) << 8;
	Log.i(TAG, "minor - " + Integer.toHexString(minor));

	// read txpower
	this.txpower = (int) src[29];
	Log.i(TAG, "txpower - " + txpower);

	return this;
}

用PC发送iBeacon信号做测试

启动蓝牙模块

sudo hciconfig hci0 up

设置iBeacon广播内容,注意符合iBeacon协议中规定的字段

sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00 01 00 02 C5 00

开始广播(LE advertise)

sudo hciconfig hci0 leadv

停止广播

sudo hciconfig hci0 noleadv

另外

GitHub上有一个工程是一个公司专门在Android上做的iBeacon的移植,但是由于不明原因被删除的公开的代码,不过在其历史提交记录中还是可以看到删除前的代码,至于删除原因该公司没有说明,给出的咨询邮箱没有回复。