首页 > 解决方案 > BLE 广告在 Android 中的变化

问题描述

我对 android 和 BLE 很陌生。目前,我正在尝试宣传一个在 android 低谷 BLE 中周期性变化的数据包。我使用了https://source.android.com/devices/bluetooth/ble_advertising中提供的以下代码。

BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
        AdvertisingSetParameters parameters = (new AdvertisingSetParameters.Builder())
                .setLegacyMode(true) // True by default, but set here as a reminder.
                .setConnectable(false)
                .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
                .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_HIGH)
                .build();
        AdvertiseData data = (new AdvertiseData.Builder()).setIncludeDeviceName(true).build();

        final AdvertisingSet[] currentAdvertisingSet = new AdvertisingSet[1];
        //final AdvertisingSet[] currentAdvertisingSet = {null};
        AdvertisingSetCallback callback = new AdvertisingSetCallback() {
            @Override
            public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
                Log.i(LOG_TAG, "onAdvertisingSetStarted(): txPower:" + txPower + " , status: "
                        + status);
                currentAdvertisingSet[0] = advertisingSet;
            }

            @Override
            public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {
                Log.i(LOG_TAG, "onAdvertisingDataSet() :status:" + status);
            }

            @Override
            public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {
                Log.i(LOG_TAG, "onScanResponseDataSet(): status:" + status);
            }

            @Override
            public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
                Log.i(LOG_TAG, "onAdvertisingSetStopped():");
            }
        };

        //start advertising
        advertiser.startAdvertisingSet(parameters, data, null, null, null, callback);

        //change the advertising packet
        currentAdvertisingSet[0].setAdvertisingData(new AdvertiseData.Builder().setIncludeDeviceName(true).setIncludeTxPowerLevel(true).build());

但是当我尝试分配一个新的广告数据作为我得到的最后一行时

Attempt to invoke virtual method 'void android.bluetooth.le.AdvertisingSet.setAdvertisingData(android.bluetooth.le.AdvertiseData)' on a null object reference

错误和应用程序以setLegacyMode true 和 false 关闭。但是我已经在public void onAdvertisingSetStarted函数中分配了adsSet 。我应该在这里做什么?

标签: androidbluetoothbluetooth-lowenergybeacon

解决方案


currentAdvertisingSet[0]显示的代码导致 NullPointerException 的原因是因为它在您为该数组元素分配值之前 尝试访问。

当代码初始化它时final AdvertisingSet[] currentAdvertisingSet = new AdvertisingSet[1];,数组的内容被初始化,每个元素都设置为 null。在执行之前,代码不会初始化currentAdvertisingSet[0]为非空值AdvertisingSetCallback。这是异步的,将调用advertiser.startAdvertisingSet(...).

currentAdvertisingSet[0].setAdvertisingData(...)问题是当下一行在几微秒后执行时,这个回调还没有发生。当它执行时,currentAdvertisingSet[0]元素还没有被初始化——它仍然是空的。这就是代码崩溃的原因。

要解决此问题,您必须等到currentAdvertisingSet[0]它被初始化后再使用。你当然可以添加一个检查if (currentAdvertisingSet[0] != null)来防止崩溃,但是在显示的代码中这永远不会是真的,所以代码永远不会执行。

最终,您需要移动更改广告集的代码,以便稍后执行。您可以将此代码放在回调中,但这对您的用例可能没有意义——开始广告然后立即将其更改为其他内容可能没有意义。


推荐阅读