hello大家好,我是城乡经济网小晟来为大家解答以上问题,安卓蓝牙开发,Android低功耗蓝牙总结很多人还不知道,现在让我们一起来看看吧!
首先要搞清楚一点,我们在 Android 中通过 SDK 获得的蓝牙广播包是经过底层的 SDK 给我们处理过的,是一个长度为 62 的字节数组。这个长度为 62 的字节数组是怎么来的呢?
想要搞清楚这个问题,首先我们要明白 iBeacon 向外发送的最原始的广播包是什么样的?
【资料图】
首先我们要搞清楚一点,蓝牙在向外发送数据的时候是分成两个部分的一个就是普通的广播包还有一个叫做应答包。这是蓝牙协议的规定内容,针对于所有的蓝牙设备(iBeacon 只是蓝牙设备的一种)
需要注意的是,发送数据是从低位到高位一次发送,所以接收到的数据要返回来按字节拼接,例如接收到的MAC为 8b 03 00 b0 01 c2,那么实际的MAC为 c2:01:b0:00:03:8b
首先我们来看一下第一个蓝牙广播包(来自 iBeacon 设备),一共 59 个字节
04 3e 38 0d 01 13 00 01 8b 03 00 b0 01 c2 01 00 ff 7f af 00 00 00 00 00 00 00 00 00 1e 29个字节 02 01 06 1a ff 4c 00 02 15 fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25 27 11 4c b9 c5 30个字节
第一行的内容可以认为是蓝牙广播包中的附带信息,通过 Android SDK 是没法看到的,第二行是对应我们 Android SDK 中收到的广播包中的前一部分。
第一个字节是HCI Packet Type,04表示这是HCI Event;剩下的58bytes则是HCI Event的具体内容第二个字节是EventCode,3e是此事件的代码;第三个字节是Parameter Length,0x38(十进制56)表示后面数据长度56bytes第四个字节是SubEvent,0d表示这是LE Extended Advertising Report;第五个字节是Num Reports,数值为011b 00这两个字节代表Event Type,由于发送数据都是按字节发送以及从低位向高位发送,因此真实值是 001b01 表示这是随机设备地址8b 03 00 b0 01 c2 是此设备的MAC,根据从低向高的发送规则,所以真实MAC是 c2:01:b0:00:03:8b01 代表首要广播信道的带宽00 代表次要广播信道的带宽,此处表示不使用次要信道ff 表示广播SID7f 代表Tx Power的大小,此处是127dbmaf 代表RSSI的大小,此处是-81dbm00 00 代表周期广播间隔00 代表直接地址类型,次数是公共设备地址00 00 00 00 00 00 代表直接BD_ADDR1e 代表接下的的数据的字节数(长度),以下数据就是最重要的广播数据了
上面的内容就是对应第一行的解释了,其实 Android SDK 已经帮我们把这些数据中的部分内容解析出来,我们可以直接通过对应的 SDK 的方法来直接获取。
下面我们再来看 真正意义上的广播包
格式是这样的:
一个广播包是由若干个广播单元 AD Structure 构成的。每个 AD Structure 的组成是:第一个字节表示长度值 length,表示接下来的 length 个字节是数据部分,数据部分的第一个字节表示数据的类型 AD Type,AD Type 决定了下面的数据代表了什么,关于每个数值代表的数据类型见官方文档,剩下的 length - 1 个字节表示真正的数据
02 01 06 02 表示接下来的数据有两个字节 01 表示数据类型,此处类型是 Flags 06 就是具体的数值了 0x06 = 0000 0110 每一位都有不同的含义,见官方文档
1a ff 4c 00 02 15 fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25 27 11 4c b9 c51a 表示接下来的数据有 26 字节FF 表示数据类型,此处类型是 厂商自定义数据类型(这里的厂商指的是苹果公司,因为 iBeacon 是苹果公司提出的)4C 00 表示公司的 ID,此处的 004C 代表苹果公司02 15 Beacon 的标识位,必须是这样的fd a5 06 93 a4 e2 4f b1 af cf c6 eb 07 64 78 25表示 Beacon UUID 27 11 是 major 的值4C b9 是 minor 的值C5 表示 Measured Power 表示的是此设备在 1 米处的 RSSI 值,用于距离测算
这段内容其实主要是苹果公司在蓝牙协议的基础上定义的。
如果符合 1AFF4C000215 则说明此设备是 iBeacon 设备
04 3e 38 0d 01 1b 00 01 8b 03 00 b0 01 c2 01 00 ff 7f af 00 00 00 00 00 00 00 00 00 1e 29个字节02 0a 00 08 16 f0 ff 64 27 11 4c b9 11 09 4d 69 6e 69 42 65 61 63 6f 6e 5f 30 30 39 30 37 30个字节
其中第一行与上面一样,这里不再介绍02 0a 00 02 表示接下来的数据长度 2 个字节0a 表示数据类型 这里表示 Tx Power Level 取值范围是 -127 到 127 dBm00 表示 0 dBm08 16 f0 ff 64 27 11 4c b908 表示数据长度 16 表示 Service Data 由 Service UUID 和 service 数据组成 前两个字节是 UUID 后面是数据f0ff 是 Service UUID 64 27 11 4c b9 是数据11 09 4d 69 6e 69 42 65 61 63 6f 6e11 表示数据长度09 表示设备完整的名字4d 69 6e 69 42 65 61 63 6f 6e 就是设备名字的 ASSIC 码了 对应 MiniBeaconM i n i B e a c o n 5f 30 30 39 30 37这几个数据就是 Beacon 开发者随便乱加入的数据了,不符合协议内容
上面我们分别分析了蓝牙原始数据包中的广播包和应答包,其实对于 iBeacon 来说广播包中的大多数内容其确定的,只有 UUID Major Minor 会有变化。而且每个位置所代表的作用都已经被 苹果公司 定义好了。如果想要 iBeacon 发出的数据包有更多的内容,那么我们就可以在应答包中做文章了,应答包是有 32 个字节的。我们只需要按照协议的内容向应答包中添加数据就可以了。
对于 Android 客户端,通过 Scanresult.getScanRecord().getBytes() 获得的广播包是 62 个字节,它把上面原始数据包中的内容提取出来了,只保留了第二行内容。就是 蓝牙广播包第二行(30 byte) 蓝牙应答包第二行(最多 32 byte,数目不确定),如果位数不够的话就用 0 补充。
所以我们现在就可以很好根据获得的 byte[] 数组来解析广播包了。
// 现在就获得广播包了byte[] result = ScanResult.getScanRecord().getBytes();// UUID 包含 result[9] 和 result[24]result[9]---result[24];// Majorresult[25] result[26]// Minorresult[27] result[28] // Measured Powerresult[29] // 一般我们都是直接会先把 广播包转成 16 进制的格式然后来截取String uuid = broadcast.substring(18, 50); // 至于后面应答包的内容就要根据具体的广播包格式来进行解析了,比如你们公司的硬件开发人员把电池电量放入了里面,那么你们就约定好放在什么位置,到时候你直接取就可以了。
这几个方法所获得内容都不是直接从 Android 中收到的广播(ScanResult.getScanRecord().getBytes())中解析出来的,而是从原始数据包中解析的。
getTxPower 获取传输功率,如果这个 iBeacon 不支持的话,那么结果就是 127
后面这几个方法作用不大,关键看设备是否支持
关键方法
ScanRecord 中的这几个方法就很重要的,这几个方法都和我们收到的广播包有关系。
比如:如果应答包中对 Tx Power Level 进行了设置我们就可以通过 getTxPowerLevel() 来直接获取。比如上面例子中的广播包,通过调用方法 getTxPowerLevel() 就可以得到 0
其他方法类似,只要你的应答包中数据的格式正确,就可以解析出来。
举例说明:
比如 Android 端收到的广播包是:
0201061AFF4C0002150123456789ABCDEF0123456789ABCDEF00000007C5 广播包020A00 0303F1FF 0E16F1FF6400000007AC233F66C401 070965526F7574650000 应答包
getTxPowerLevel() 返回 0 因为在应答包中有正确的格式数据 020A00
getServiceData() 也会返回值,因为在应答包中有对应的数据 0E16F1FF6400000007AC233F66C401
0E 表示数据长度16 表示类型 此处表示 Service Data - 16-bit UUID (不仅仅是 UUID 还带有数据) 前两个字节表示 UUID 后面是数据F1FF 表示 UUID6400000007AC233F66C401 表示数据 Map
List
同样的下面几个方法也是对 Android 端收到的 62 byte 的广播包中数据的解析所得
String getDeviceName() 获得是名字 需要广播包中有对应的数据 070965526F7574650000
SpareArray
byte[] getManufacturerSpecificData(int manufacture) 根据制造商代码(4c 对应的十进制)获得byte[] (0215)
还是有一些字段翻译过来不够精细,详细见官方文档:www.bluetooth.com/specificati…
Android核心知识点笔记github:https://github.com/AndroidCot/Android
本文就为大家讲解到这里,希望对大家有所帮助。
关键词:
hello大家好,我是城乡经济网小晟来为大家解答以上问题,安卓蓝牙开发
吴秀波老婆个人资料,吴秀波个人资料这个很多人还不知道,现在让我们一
钢绞线理论重量表15 2,钢绞线理论重量这个很多人还不知道,现在让我们
河蟹吃什么食物怎么养,河蟹吃什么食物这个很多人还不知道,现在让我们
1s15 2钢绞线什么意思,s152钢绞线理论重量这个很多人还不知道,现在让
lepetitprince,princejackson这个很多人还不知道,现在让我们一起来看
今日LPL夏季赛WE在面对TES第二局时,Tian连续抢走两条WE的龙。赛后WE打
今日LPL夏季赛TES惨遭WE横扫,赛后TES全员接受媒体群访,详情如下:Q:
直播吧6月26日讯15:00JDGvsNIP17:00WBGvsFPX19:00BLGvsIG解说:彭彭、
杭州亚运会电子竞技项目名单公开,其中王者荣耀亚运版项目的阵容也确定
昨日官方公布了杭州亚运会LOL队伍的阵容名单,详细阵容为白家浩(369)
1、我建议你去动漫网站找找看 要不实在没有的话,就去卖影碟的地方看看
1、挺好的。2、不过他不更新了…算了吧,三西贝垃圾的没人看!审判这...
巨星单场60分次数:杜兰特0次,哈登4次,科比6次,詹姆斯多少次,新秀阵
美媒列出现役一人一城时间最长的五人,谁有可能一人一城结束生涯,乔丹,
克里斯保罗职业生涯带队战绩揭秘,是勇士的夺冠拼图之一吗,快船队,勇士
美媒列出2023年休赛季,球迷们最想看到的五笔交易,交易,美媒,快船队,利
湖人交易倒计时!3笔交易,均让湖人重回夺冠大热门,湖人,哈登,特纳,比
什么是化工壶又该如何鉴别,什么是化工这个很多人还不知道,现在让我们
一意孤行电影,一意孤行这个很多人还不知道,现在让我们一起来看看吧!1
问药朱紫国剧情怎么配药,问药朱紫国这个很多人还不知道,现在让我们一
刑满释放人员社保政策最新,刑满释放人员社保政策这个很多人还不知道,
高三班主任评语200字男生,高三班主任评语200字这个很多人还不知道,现
在2023LPL夏季赛常规赛今日的比赛中,TES0-2不敌WE。本期视频为打野选
直播吧6月26日讯 在2023LPL夏季赛常规赛W5D1的第二场比赛中,WE2-0战
今日WE成功战胜TES,赛后全员接受了胜者群访:1、问Cube:第一场16分钟
今日LPL夏季赛WE成功击败TES终结队伍在夏季赛的两连败,赛后WE上单Cube
直播吧6月26日讯-冷静点60e们,赢个TES闹麻了-是啊,想象一下Hope会输
1、画一个三角形2、画十字条纹3、有规律地画画4、画眉毛和眼睛5、画出
据深圳发布,6月26日,市市场监管局、中国人民银行深圳市中心支行联合
广告
X 关闭
广告
X 关闭