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种蓝牙设备:
- Bluetooth:仅仅支持传统模式的蓝牙设备
- Bluetooth Smart Ready:支持传统和低功耗两种模式设备
- Bluetooth Smart:仅仅支持低功耗蓝牙设备
BLE与传统的蓝牙相比最大的优势是功耗减少90%,同一时候传输距离增大(超过100米)、安全和稳定性提高(支持AES加密和CRC验证)。
iBeacon同一时候有一些自己的特点:
- 无需配对,一般蓝牙设备印象中都须要配对工作。iBeacon无需配对,由于它是採用蓝牙的广播频道传送信号。
- 程序能够后台唤醒,iBeacon的信息推送须要App支持。
可是我们接收iBeacon信号无需打开App,仅仅要保证安装了,同一时候手机蓝牙打开。
iBeacon是怎样工作呢?实际上iBeacon基站通过蓝牙的广播频道不断向外发送位置信息,发送频率越快越耗电。也就是说iBeacon并不推送消息,而仅仅是用于定位,推送消息的功能必须由App来完毕。苹果定义了iBeacon 当中32位广播的数据格式。
- UUID:厂商识别号
- Major:相当于群组号,同一个组里Beacon有同样的Major
- Minor:相当于识别群组里单个的Beacon
- TX Power:用于測量设备离Beacon的距离
UUID+Major+Minor就构成了一个Beacon的识别号,有点类似于网络中的IP地址。TX Power用于測距。iBeacon眼下仅仅定义了大概的3个粗略级别:
- 很近(Immediate): 大概10厘米内
- 近(Near):1米内
- 远(Far):1米外
这里主要是对其使用方法做一个介绍:
首先是获取BluetoothAdapter对象:
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); mBluetoothAdapter.startLeScan(mLeScanCallback);
然后就是它的回调。在这里对搜索到的iBeacon设备距手机的信号强度做了一个排序
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<iBeacon>() { @Override public int compare(iBeacon h1, iBeacon h2) { return h2.rssi - h1.rssi; } }); } };最后把搜索到的数据加入到集合中去
private ArrayList<iBeacon> mLeDevices = new ArrayList<iBeacon>(); private void addDevice(iBeacon device) { //更新beacon信息 if(device==null) { Log.d("DeviceScanActivity ", "device==null "); return; } for(int i=0;i<mLeDevices.size();i++){ String btAddress = mLeDevices.get(i).bluetoothAddress; if(btAddress.equals(device.bluetoothAddress)){ mLeDevices.add(i+1, device); mLeDevices.remove(i); break; } } mLeDevices.add(device); }
我们在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(); } }