編輯:關於Android編程
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);
然後就是它的回調,在這裡對搜索到的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最後把搜索到的數據添加到集合中去() { @Override public int compare(iBeacon h1, iBeacon h2) { return h2.rssi - h1.rssi; } }); } };
private ArrayListmLeDevices = 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(); } }
Volley是Android系統下的一個網絡通信庫,為Android提供簡單快速的網絡操作(Volley:Esay, Fast Networking for Androi
本文為大家講解的是Android Studio安裝後啟動時Fetching android sdk component information超時的解決方案,感興趣的同
問題起因我曾經在開發Android Application的過程中遇到過那個有名的65k方法數的問題。如果你開發的應用程序變得非常龐大,你八成會遇到這個問題。這個問題實際
一、---框架---1、新建一個布局文件,輸入我們想要使用的線程的個數,包括一個主布局文件和一個progressBar(1)一個包括三個控件的主布局(2)一個只包含Pro