Beacon 和 Eddystone 检测问题

问题描述

问题包括检测 IBeacon 和 Eddystone 帧,当我拥有 Eddystone 时,我必须使用特定的功能,IBeacon 也是如此。 我在 Android Studio 中使用 Java,因此为我提供 IBeacon 结果的函数是 getManufatureSpecificData(),而 Eddystone 的函数是 getServiceData()。 问题是为什么会有不同的功能来产生结果?以及如何检查接收到的帧是 Eddystone 还是 IBeacon?

代码片段

    public void onBatchScanResults(List<ScanResult> results) {
        super.onBatchScanResults(results);
        beaconManager.clean();
        Log.i(TAG,"On batch called,size of result is : " + results.size());

        for (int index = 0; index < results.size(); ++index) {
            try {
                ScanRecord mScanRecord = results.get(index).getScanRecord();
                Map<ParcelUuid,byte[]> myMap = mScanRecord.getServiceData();
                int mRsi = results.get(index).getRSSi();
                String url = "";
                byte[] txPower = new byte[1];
                byte[] nameSpaceId = new byte[10];
                byte[] instanceId = new byte[6];
                float distance;
                
                for (Map.Entry<ParcelUuid,byte[]> eddystoneFrame : myMap.entrySet()) {
                    // for eddystone URL
                    if (eddystoneFrame.getValue()[0] == 16) {
                        url += urlSchemePrefix[eddystoneFrame.getValue()[2]];

                        for (int i = 3; i < eddystoneFrame.getValue().length - 1; i++) {
                            url += (char) eddystoneFrame.getValue()[i];
                        }

                        url += topLevelDomain[eddystoneFrame.getValue()[eddystoneFrame.getValue().length - 1]];
                        txPower[0] = eddystoneFrame.getValue()[1];
                        distance = (float) Utils.calculatedistance((int) txPower[0],(double) mRsi);
                        
                        try {
                            beaconManager.addEddyBeacon(Utils.bytesToHex(nameSpaceId),Utils.bytesToHex(instanceId),distance);
                        } catch (Exception e) {
                            Log.e(TAG,e.toString());
                        }

                    }
                    else if (eddystoneFrame.getValue()[0] == 0) {
                        // For Eddystone UID
                        System.arraycopy(eddystoneFrame.getValue(),2,nameSpaceId,nameSpaceId.length);
                        System.arraycopy(eddystoneFrame.getValue(),12,instanceId,instanceId.length);
                        System.arraycopy(eddystoneFrame.getValue(),1,txPower,txPower.length);

                        distance = (float) Utils.calculatedistance((int) txPower[0],(double) mRsi);

                        /**  beaconList.add(new String[]{"Name Space ID : " + Utils.bytesToHex(nameSpaceId)+ "\n" + "Instance ID :" + Utils.bytesToHex(instanceId),String.format("%.2f",distance),"eddystoneuid"});**/
                        try {
                            beaconManager.addEddyBeacon(Utils.bytesToHex(nameSpaceId),e.toString());
                        }

                    }
                    Log.i(TAG,"The size of the frame is: " + eddystoneFrame.getValue().length);
                }


            } catch (Exception e) {
                Log.e("Error123456789",e.toString());
                break;
            }
        }

解决方法

蓝牙 SIG 标准机构定义了两种蓝牙 LE 广告:

  1. GATT 服务广告 - 这些广告旨在宣传 GATT 服务,并且可能包含服务数据字节,旨在告诉您有关所广告服务的一些信息。
  2. 制造商广告 - 这些广告专为蓝牙设备制造商希望使用的任何目的而设计。它们始终包含 0-24 字节的制造商数据。

Apple 在设计 iBeacon 格式时,选择使用制造商广告。因此,无论何时检测到它们,您都必须获取制造商数据以对内容进行解码。

当 Google 设计 Eddystone 时,它​​选择不使用制造商广告,而是使用 GATT 服务广告。它做出这个选择是因为它希望他的格式在 iOS 设备上运行良好,而 iOS 通常拒绝让 3rd 方应用在后台检测制造商广告(iBeacon 除外)。

由于 Google 的这一设计决定,您在尝试解码 Eddystone 广告时必须检查是否有服务数据。

如果您想检测两种信标类型,请使用如下逻辑:

  1. 是否有附加的服务数据?如果否,请转到第 3 步。
  2. 服务数据可以解码为 Eddystone 吗?如果是,我们就完成了。
  3. 该广告是制造商广告吗?如果否,请转到第 5 步。
  4. 是否可以在 iOS 上解码制造商数据,如果是,我们就完成了。
  5. 该广告既不是 Eddystone 也不是 iBeacon。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...