简体   繁体   English

在Android中读取广告包

[英]Read advertisement packet in Android

I'm working on a BLE sensor that is advertising manufacturer specific data.我正在研究一个 BLE 传感器,它是广告制造商特定的数据。 Is there any sample code that demonstrates how to receive an advertisement packet in Android and parse its payload?是否有任何示例代码演示如何在 Android 中接收广告数据包并解析其有效负载?

This is what I was looking for:这就是我要找的:

The BLE scan API BluetoothAdapter.startLeScan(ScanCallback) requires a call back function for the scan results. BLE 扫描 API BluetoothAdapter.startLeScan(ScanCallback) 需要扫描结果的回调函数。 the method needs to look like the following:该方法需要如下所示:

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

And the scanRecord variable is a byte array which contains the Advertisement packet payload. scanRecord 变量是一个字节数组,其中包含广告数据包负载。

Per the BLE specification the structure of the payload is very simple as follows:根据 BLE 规范,有效载荷的结构非常简单,如下所示:

The packets can be up to 47 bytes in length and consist of:数据包最长可达 47 个字节,包括:

  • 1 byte preamble 1 字节序言
  • 4 byte access address 4字节访问地址
  • 2-39 bytes advertising channelPDU 2-39 字节广告 channelPDU
  • 3 bytes CRC 3 字节 CRC

For advertisement communication channels, the access address is always 0x8E89BED6.对于广告通信通道,访问地址始终为 0x8E89BED6。

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). PDU 又具有自己的标头(2 个字节:有效载荷的大小及其类型——设备是否支持连接等)和实际有效载荷(最多 37 个字节)。

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.最后,payload的前6个字节是设备的MAC地址,实际信息最多可以有31个字节。

the format of the actual information is as follows:实际信息的格式如下:

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;
        }
    }

thanks to谢谢

how-ibeacons-work信标如何工作

bluetooth org specs 蓝牙组织规格

mass for putting me on the right direction!质量让我朝着正确的方向前进!

ADPayloadParser in nv-bluetooth parses the payload of an advertising packet and returns a list of AD structures. nv-bluetooth 中的ADPayloadParser解析广告数据包的负载并返回 AD 结构列表。 The AD structure format is described in "11 ADVERTISING AND SCAN RESPONSE DATA FORMAT" of "Bluetooth Core Specification 4.2". AD结构格式在“Bluetooth Core Specification 4.2”的“11 ADVERTISING AND SCAN RESPONSE DATA FORMAT”中有描述。

The following code snippet is an implementation example of onLeScan method.以下代码片段是onLeScan方法的实现示例。

public void onLeScan(
    BluetoothDevice device, int rssi, byte[] scanRecord)
{
    // Parse the payload of the advertising packet.
    List<ADStructure> structures =
        ADPayloadParser.getInstance().parse(scanRecord);

    // For each AD structure contained in the advertising packet.
    for (ADStructure structure : structures)
    {
        if (structure instanceof IBeacon)
        {
            // iBeacon packet was found.
            handleIBeacon((IBeacon)structure);
        }
        ......
    }
}

You can register a parser of your own for your manufacturer-specific format into ADPayloadParser.您可以为您的制造商特定格式注册您自己的解析器到 ADPayloadParser。 Refer to the following links for more information.有关详细信息,请参阅以下链接。

Blog: http://darutk-oboegaki.blogspot.jp/2015/03/ibeacon-as-kind-of-ad-structures.html博客: http : //darutk-oboegaki.blogspot.jp/2015/03/ibeacon-as-kind-of-ad-structures.html

GitHub: https://github.com/TakahikoKawasaki/nv-bluetooth GitHub: https://github.com/TakahikoKawasaki/nv-bluetooth

JavaDoc: http://takahikokawasaki.github.io/nv-bluetooth/ JavaDoc: http : //takahikokawasaki.github.io/nv-bluetooth/

Maven: http://search.maven.org/#search|ga|1|a%3A%22nv-bluetooth%22 Maven: http : //search.maven.org/#search| ga|1|a%3A%22nv- bluetooth%22

edit 21.02.2016编辑 21.02.2016

The library i linked below seems to have been moved;我在下面链接的图书馆似乎已被移动; see https://github.com/AltBeacon/android-beacon-libraryhttps://github.com/AltBeacon/android-beacon-library


You can use Android iBeacon Library for a start.您可以先使用 Android iBeacon 库。

There is a reference application which you can use for the basics and with simulated data.有一个参考应用程序,您可以将其用于基础知识和模拟数据。 ~ https://github.com/RadiusNetworks/ibeacon-reference-android~ ~ https://github.com/RadiusNetworks/ibeacon-reference-android~

Once you get it up and running you may wish to import the library and use it with your real device, there is also some example code on the site: http://developer.radiusnetworks.com/ibeacon/android/samples.html启动并运行后,您可能希望导入库并将其用于您的真实设备,站点上还有一些示例代码: http : //developer.radiusnetworks.com/ibeacon/android/samples.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM