Android BLE-iBeacon系列(二)扫描识别iBeacon设备


干货分享:Android BLE 框架,简单易用,可能是迄今为止功能最全面的
https://github.com/a1anwang/okble


iBeacon系列文章:

\color{red}{注:iBeacon是苹果在BLE基础上的封装,android系统没有提供Beacon相关的封装}
\color{red}{本文iBeacon系列代码是完全按照ios的api来设计的,在APP开发时android和ios的逻辑是一模一样的}
Android BLE-iBeacon系列(一)iBeacon介绍
Android BLE-iBeacon系列(二)扫描识别iBeacon设备
Android BLE-iBeacon系列(三)iBeacon区域介绍
Android BLE-iBeacon系列(四)iBeacon区域的进入和退出监听
Android BLE-iBeacon系列(五)手机模拟为iBeacon(待续)


正文

扫描

iBeacon设备就是一个BLE设备,所以扫描方法和BLE扫描方法一样的:

 bluetoothAdapter.startLeScan( leScanCallback);  
 private LeScanCallback leScanCallback=new LeScanCallback() { 
         @Override 
         public void onLeScan(BluetoothDevice bluetoothdeivce, int rssi, byte[] scandata) {
                //把byte数组转成16进制字符串,方便查看 
                Log.e("TAG","scandata:"+ Bytes2HexString(scandata) +" rssi:"+rssi);
         } 
 };
//这里使用的android 4.3的API,android 5.0开始扫描API做了一点变化,为了获得更大的兼容性,我们依然使用的4.3的API。
//不需要兼容4.3的推荐使用android 5.0 的API,官方已经帮助我们封装了很多,使用起来更简单

这样扫描到的是所有的BLE设备,接下来要识别BLE设备是不是iBeacon设备

识别

识别就是通过扫描回调里的byte[] scandata来进行判断,判断依据就是苹果公司规定的iBeacon的广播格式:


iBeacon的广播格式

这个广播格式规定了iBeacon的广播数据是30个字节,第0,1,2字节是BLE4.0的协议固定格式,第3字节 length ,0x1A(16进制的1A等于10进制26)表示后面的数据是26个字节长度(3+1+26=30没毛病)。
再看第4字节名称是Type,数据0xFF,也是BLE4.0协议里的,顾名思义,0xFF表示的是一个类型,是厂商数据类型,表示后面的25个字节就是厂商数据(Manufacturer Data,BLE设备厂商可以自定义这部分数据,Manufacturer Data 由两部分构成:厂商id和数据部分)。Manufacturer Data里的前2个字节也就是第5-6字节,是厂商的id,固定占2个字节,苹果的公司id是0x004C(苹果公司向世界蓝牙组织申请的,不同的公司有不同的id),表示这个设备使用的是苹果的协议,后面的第7-8字节是苹果规定的固定的0x0215,表示这个设备是苹果的iBeacon设备,再就是iBeacon设备的uuid,major,minor等信息了。关于BLE设备广播数据的分析,可以看这篇文章,会更加了解一些:

废话不多说了,根据这个协议,立马写出如下的判断方法:

if(scandata[5]==0x4C&&scandata[6]==0x00&&scandata[7]==0x02&&scandata[8]==0x15) {
  //这是一个iBeacon设备。
  //注意这里004C的判断,在广播里厂商id这2个字节的数据是颠倒的
}

这种写法完全没毛病,不过可能看来不够高大上,并且体现不了BLE广播的结构,如果之前已经看过关于BLE设备广播数据的分析,那么我们可以直接拿来用的:

        //这里用了android 5.0 API扫描结果来演示
       //上面提到的okble框架在4.3基础上封装的跟5.0 API一样,喜欢的可以直接用
        SparseArray<byte[]> manufacturerData= scanResult.getManufacturerSpecificData();
        int size_1=manufacturerData.size();
        for (int i=0;i<size_1;i++){
            int key=manufacturerData.keyAt(i);
            byte[] value=manufacturerData.get(key);
            if(key==0x004C) {//0x004c is apple company id
                if(value!=null && value.length==23&& value[0]==0x02&&value[1]==0x15){
                   //this is an iBeacon
                    
                }
            }
        }

这样判断虽然看起来好像复杂了点,但是体现了BLE广播的解析方法。
如果你的项目只用到iBeacon,我还是推荐使用第一种简便判断法的,效率会高点

解析

识别到是iBeacon后,然后解析出对应的uuid,major,minor等信息。
按照上面的协议图,解析很简单,代码如下(以第一种识别方法):

byte[] uuidValue=new byte[16];
System.arraycopy(scandata, 9, uuidValue, 0, 16);
String uuid="";
String hexStr=BytesToHexString(uuidValue);
uuid=hexStr.substring(0, 8);
uuid+="-";
uuid+=hexStr.substring(8, 12);
uuid+="-";
uuid+=hexStr.substring(12, 16);
uuid+="-";
uuid+=hexStr.substring(16, 20);
uuid+="-";
uuid+=hexStr.substring(20, 32);
int major=buildUint16(scandata[25], scandata[26]);
int minor=buildUint16(scandata[27], scandata[28]);
int measuredPower= scandata[29];

-------↓↓↓↓↓↓工具类↓↓↓↓↓↓↓----------
    private final static byte[] hex = "0123456789ABCDEF".getBytes();

    /**
     *  字节数组转十六进制字符串
     *
     * @param b: byte[] bytes_1=new byte[]{(byte) 0xA0,(byte) 0xB1,2}
     * @return "A0B102"
     */
    public static String BytesToHexString(byte[] b) {
        if(b==null){
            return null;
        }
        byte[] buff = new byte[2 * b.length];
        for (int i = 0; i < b.length; i++) {
            buff[2 * i] = hex[(b[i] >> 4) & 0x0f];
            buff[2 * i + 1] = hex[b[i] & 0x0f];
        }
        return new String(buff);
    }
    /**
     * 高低位 组成int,
     * @param hi
     * @param lo
     * @return
     */
    public static int buildUint16(byte hi, byte lo) {
        return (int) ((hi << 8) + (lo & 0xff));
    }

封装

使用起来的话,稍微封装一下会更好用,
直接用上面的OKBLE框架可以不用看下面的了;return;


public class BeaconScanManager {
    
    BluetoothAdapter bluetoothAdapter;
    
    private BeaconListener beaconListener;
    
    public void setBeaconListener(BeaconListener beaconListener) {
        this.beaconListener = beaconListener;
    }
    
    public BeaconScanManager(Context context) {
        BluetoothManager bluetoothManager=(BluetoothManager)context. getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter= bluetoothManager.getAdapter();
    }


    public void startScanBeacon(){
        bluetoothAdapter.stopLeScan(leScanCallback);
        bluetoothAdapter.startLeScan(leScanCallback);
    }

    public void stopScan(){
        bluetoothAdapter.stopLeScan(leScanCallback);
    }
    private LeScanCallback leScanCallback=new LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice bluetoothdeivce, int rssi, byte[] scandata) {
            if(scandata[5]==0x4C&&scandata[6]==0x00&&scandata[7]==0x02&&scandata[8]==0x15) {
              //这是一个iBeacon设备。
              //注意这里004C的判断,在广播里厂商id这2个字节的数据是颠倒的
              ...//这里是解析uuid,major,minor代码,省略
              Beacon beacon=new Beacon(uuid,major,minor);
              if(beaconListener!=null){
                    beaconListener.onScanBeacon(beacon);
              }
            }
        }
    };
    public interface BeaconListener{
        public void onScanBeacon(Beacon beacon);
    }
}
   public class Beacon{
        public int major;
        public int minor;
        public String uuid;
        public Beacon(String uuid, int major, int minor){
             this.uuid=uuid;
             this.major=major;
             this.minor=minor;
        }
        @Override
        public String toString() {
            return " uuid:"+uuid+" major:"+major+" minor:"+minor;
        }
    }

使用

public class MainActivity extends AppCompatActivity implements BeaconScanManager.BeaconListener {
    
    BeaconScanManager beaconScanManager;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        beaconScanManager = new BeaconScanManager(this);
        beaconScanManager.setBeaconListener(this);
        
    }
    public void scanAction(View v) {
        beaconScanManager.startScanBeacon();
    }
    //扫描回调
    @Override
    public void onScanBeacon(Beacon beacon) {
        Log.e(TAG, "  beacon设备:" + beacon.toString());
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 因为自己的项目中有用到了蓝牙相关的功能,所以之前也断断续续地针对蓝牙通信尤其是BLE通信进行了一番探索,整理出了一...
    陈利健阅读 114,595评论 172 294
  • 干货分享:Android BLE 框架,简单易用,可能是迄今为止功能最全面的https://github.com/...
    Holly_dd20阅读 9,421评论 0 5
  • BLE广告和信标 (原文) BLE广告是蓝牙低功耗最重要的方面之一。 了解如何正确使用广告可以帮助你降低功耗,加快...
    公子小水阅读 3,333评论 1 3
  • 文章图片上传不正常,如需文档,可联系微信:1017429387 目录 1 安装... 4 1.1 配置探针... ...
    Mrhappy_a7eb阅读 6,296评论 0 5
  • 背景 蓝牙历史说到蓝牙,就不得不说下蓝牙技术联盟(Bluetooth SIG),它负责蓝牙规范制定和推广的国际组织...
    徐正峰阅读 12,310评论 6 33