Android 開發中 iBeacon的使用


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:僅僅支持低功耗藍牙設備

estimote-ibeacon-teardown2

BLE與傳統的藍牙相比最大的優勢是功耗減少90%,同一時候傳輸距離增大(超過100米)、安全和穩定性提高(支持AES加密和CRC驗證)。

iBeacon同一時候有一些自己的特點:

  • 無需配對,一般藍牙設備印象中都須要配對工作。iBeacon無需配對,由於它是採用藍牙的廣播頻道傳送信號。
  • 程序能夠后台喚醒,iBeacon的信息推送須要App支持。

    可是我們接收iBeacon信號無需打開App,僅僅要保證安裝了,同一時候手機藍牙打開。

iBeacon是怎樣工作呢?實際上iBeacon基站通過藍牙的廣播頻道不斷向外發送位置信息,發送頻率越快越耗電。也就是說iBeacon並不推送消息,而僅僅是用於定位,推送消息的功能必須由App來完畢。蘋果定義了iBeacon 當中32位廣播的數據格式。

estimote-ibeacon-teardown3
  • 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();  
    }  
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM