zoukankan      html  css  js  c++  java
  • 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();  
        }  
    }

  • 相关阅读:
    关于unicode编码问题——[ASIS 2019]Unicorn shop
    cve-2020-7066 ssrf漏洞——GKCTF2020
    updatexml()报错注入——[极客大挑战 2019]HardSQL
    用户名和密码分开检验产生的mysql注入——[GXYCTF2019]BabySQli
    安恒月赛——Ezunserialize(反序列化字符逃逸)
    记一次Flask模板注入学习 [GYCTF2020]FlaskApp
    [CISCN2019 华北赛区 Day2 Web1]Hack World
    [SUCTF 2019]CheckIn(user.ini文件构成的php后门)
    sql注入用<>绕过被过滤的select ——百度杯9月第二场SQL
    剑指offer32 从上到下打印二叉树(叁)
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6920897.html
Copyright © 2011-2022 走看看