iBeacon的工作原理是基于Bluetooth Low Energy(BLE)低功耗蓝牙传输技术,iBeacon基站不断向四周发送蓝牙信号,当智能设备进入设定区域时,就能够收到信号。只要满足iBeacon技术标准的都可以使用,所以Android也能够支持iBeacon。Google在Android4.3中支持BLE技术
定位一直是非常关键的功能。通过iBeacon基站的部署能够实现室内导航,同时通过蓝牙推送信息,iBeacon在商场零售或者一些公共服务领域如体育馆、博物馆能提供非常棒的体验。尤其是蓝牙不错传输距离、低功耗、以及信号加密使得iBeacon在移动支付领域也非常有前景。总之,iBeacon的潜力似乎是无穷大,也受到了越来越多的关注。
要了解iBeacon是如何工作首先我们要了解BLE。BLE(也称为Bluetooth Smart)最早追溯到Nokia于2006年提出的Wibree,后来融合进了蓝牙标准,成为Bluetooth4.0的一部分。目前我们经常能看到3种蓝牙设备:
BLE与传统的蓝牙相比最大的优势是功耗降低90%,同时传输距离增大(超过100米)、安全和稳定性提高(支持AES加密和CRC验证)。iBeacon同时有一些自己的特点:
iBeacon是如何工作呢?实际上iBeacon基站通过蓝牙的广播频道不断向外发送位置信息,发送频率越快越耗电。也就是说iBeacon并不推送消息,而只是用于定位,推送消息的功能必须由App来完成。苹果定义了iBeacon 其中32位广播的数据格式。
UUID+Major+Minor就构成了一个Beacon的识别号,有点类似于网络中的IP地址。TX Power用于测距,iBeacon目前只定义了大概的3个粗略级别:
这里主要是对其用法做一个介绍:
首先是获取BluetoothAdapter对象:
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
mBluetoothAdapter.startLeScan(mLeScanCallback);
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final iBeacon ibeacon = iBeaconClass.fromScanData(device,rssi,scanRecord);
addDevice(ibeacon);
Collections.sort(mLeDevices, new Comparator() {
@Override
public int compare(iBeacon h1, iBeacon h2) {
return h2.rssi - h1.rssi;
}
});
}
};
最后把搜索到的数据添加到集合中去
private ArrayList mLeDevices = new ArrayList();
private void addDevice(iBeacon device) { //更新beacon信息
if(device==null) {
Log.d("DeviceScanActivity ", "device==null ");
return;
}
for(int i=0;i
我们在iBbeaconClass类中对其进行数据的解析处理,参考:https://github.com/AltBeacon/android-beacon-library
public class iBeaconClass {
static public class iBeacon{
public String name;
public int major;
public int minor;
public String proximityUuid;
public String bluetoothAddress;
public int txPower;
public int rssi;
}
public static iBeacon fromScanData(BluetoothDevice device, int rssi,byte[] scanData) {
int startByte = 2;
boolean patternFound = false;
while (startByte <= 5) {
if (((int)scanData[startByte+2] & 0xff) == 0x02 &&
((int)scanData[startByte+3] & 0xff) == 0x15) {
// yes! This is an iBeacon
patternFound = true;
break;
}
else if (((int)scanData[startByte] & 0xff) == 0x2d &&
((int)scanData[startByte+1] & 0xff) == 0x24 &&
((int)scanData[startByte+2] & 0xff) == 0xbf &&
((int)scanData[startByte+3] & 0xff) == 0x16) {
iBeacon iBeacon = new iBeacon();
iBeacon.major = 0;
iBeacon.minor = 0;
iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
iBeacon.txPower = -55;
return iBeacon;
}
else if (((int)scanData[startByte] & 0xff) == 0xad &&
((int)scanData[startByte+1] & 0xff) == 0x77 &&
((int)scanData[startByte+2] & 0xff) == 0x00 &&
((int)scanData[startByte+3] & 0xff) == 0xc6) {
iBeacon iBeacon = new iBeacon();
iBeacon.major = 0;
iBeacon.minor = 0;
iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
iBeacon.txPower = -55;
return iBeacon;
}
startByte++;
}
if (patternFound == false) {
// This is not an iBeacon
return null;
}
iBeacon iBeacon = new iBeacon();
iBeacon.major = (scanData[startByte+20] & 0xff) * 0x100 + (scanData[startByte+21] & 0xff);
iBeacon.minor = (scanData[startByte+22] & 0xff) * 0x100 + (scanData[startByte+23] & 0xff);
iBeacon.txPower = (int)scanData[startByte+24]; // this one is signed
iBeacon.rssi = rssi;
// AirLocate:
// 02 01 1a 1a ff 4c 00 02 15 # Apple's fixed iBeacon advertising prefix
// e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profile uuid
// 00 00 # major
// 00 00 # minor
// c5 # The 2's complement of the calibrated Tx Power
// Estimote:
// 02 01 1a 11 07 2d 24 bf 16
// 394b31ba3f486415ab376e5c0f09457374696d6f7465426561636f6e00000000000000000000000000000000000000000000000000
byte[] proximityUuidBytes = new byte[16];
System.arraycopy(scanData, startByte+4, proximityUuidBytes, 0, 16);
String hexString = bytesToHexString(proximityUuidBytes);
StringBuilder sb = new StringBuilder();
sb.append(hexString.substring(0,8));
sb.append("-");
sb.append(hexString.substring(8,12));
sb.append("-");
sb.append(hexString.substring(12,16));
sb.append("-");
sb.append(hexString.substring(16,20));
sb.append("-");
sb.append(hexString.substring(20,32));
iBeacon.proximityUuid = sb.toString();
if (device != null) {
iBeacon.bluetoothAddress = device.getAddress();
iBeacon.name = device.getName();
}
return iBeacon;
}
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}