在Android中读取广告包 [英] Read advertisement packet in Android

查看:65
本文介绍了在Android中读取广告包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究用于宣传制造商特定数据的BLE传感器.是否有任何示例代码演示如何在Android中接收广告包并解析其有效载荷?

I'm working on a BLE sensor that is advertising manufacturer specific data. Is there any sample code that demonstrates how to receive an advertisement packet in Android and parse its payload?

推荐答案

这就是我想要的:

BLE扫描API BluetoothAdapter.startLeScan(ScanCallback)需要回调函数来获取扫描结果.该方法需要如下所示:

The BLE scan API BluetoothAdapter.startLeScan(ScanCallback) requires a call back function for the scan results. the method needs to look like the following:

    private BluetoothAdapter.LeScanCallback ScanCallback =
        new BluetoothAdapter.LeScanCallback()onLeScan(final BluetoothDevice device, 
                                                            int rssi, 
                                                      final byte[] scanRecord)
    {...}

scanRecord变量是一个字节数组,其中包含Advertisement数据包有效负载.

And the scanRecord variable is a byte array which contains the Advertisement packet payload.

根据BLE规范,有效负载的结构非常简单,如下所示:

Per the BLE specification the structure of the payload is very simple as follows:

数据包的最大长度为47个字节,包括:

The packets can be up to 47 bytes in length and consist of:

  • 1个字节的前同步码
  • 4字节访问地址
  • 2-39个字节的广告频道PDU
  • 3个字节的CRC

对于广告通信渠道,访问地址始终为0x8E89BED6.

For advertisement communication channels, the access address is always 0x8E89BED6.

PDU依次具有其自己的标头(2个字节:有效载荷的大小及其类型–设备是否支持连接等)和实际的有效载荷(最多37个字节).

The PDU in turn has its own header (2 bytes: size of the payload and its type – whether the device supports connections, etc.) and the actual payload (up to 37 bytes).

最后,有效载荷的前6个字节是设备的MAC地址,实际信息最多可以包含31个字节.

Finally, the first 6 bytes of the payload are the MAC address of the device, and the actual information can have up to 31 bytes.

实际信息的格式如下:

第一个字节是数据的长度,第二个字节是类型,后跟数据.

first byte is length of the data and second byte is type followed by the data.

这是一种聪明的方法,允许任何应用程序在不关心内容的情况下跳过整个数据记录.

This is a clever way to allow any application to skip entire data records if they don't care about the contents.

以下是确定广告包内容的示例代码:

Here is the sample code to determine the contents of the Advertisement packet:

parseAdvertisementPacket(final byte[] scanRecord) {

    byte[] advertisedData = Arrays.copyOf(scanRecord, scanRecord.length);

    int offset = 0;
    while (offset < (advertisedData.length - 2)) {
        int len = advertisedData[offset++];
        if (len == 0)
            break;

        int type = advertisedData[offset++];
        switch (type) {
            case 0x02: // Partial list of 16-bit UUIDs
            case 0x03: // Complete list of 16-bit UUIDs
                while (len > 1) {
                    int uuid16 = advertisedData[offset++] & 0xFF;
                    uuid16 |= (advertisedData[offset++] << 8);
                    len -= 2;
                    uuids.add(UUID.fromString(String.format(
                            "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
                }
                break;
            case 0x06:// Partial list of 128-bit UUIDs
            case 0x07:// Complete list of 128-bit UUIDs
                // Loop through the advertised 128-bit UUID's.
                while (len >= 16) {
                    try {
                        // Wrap the advertised bits and order them.
                        ByteBuffer buffer = ByteBuffer.wrap(advertisedData,
                                offset++, 16).order(ByteOrder.LITTLE_ENDIAN);
                        long mostSignificantBit = buffer.getLong();
                        long leastSignificantBit = buffer.getLong();
                        uuids.add(new UUID(leastSignificantBit,
                                mostSignificantBit));
                    } catch (IndexOutOfBoundsException e) {
                        // Defensive programming.
                        Log.e("BlueToothDeviceFilter.parseUUID", e.toString());
                        continue;
                    } finally {
                        // Move the offset to read the next uuid.
                        offset += 15;
                        len -= 16;
                    }
                }
                break;
            case 0xFF:  // Manufacturer Specific Data
                Log.d(TAG, "Manufacturer Specific Data size:" + len +" bytes" );
                while (len > 1) {
                    if(i < 32) {
                        MfgData[i++] = advertisedData[offset++];
                    }
                    len -= 1;
                }
                Log.d(TAG, "Manufacturer Specific Data saved." + MfgData.toString());
                break;
            default:
                offset += (len - 1);
                break;
        }
    }

感谢

how-ibeacons-work

蓝牙组织规范

质量使我朝着正确的方向前进!

mass for putting me on the right direction!

这篇关于在Android中读取广告包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆