【问题标题】:BLE Advertisements changing in AndroidBLE 广告在 Android 中的变化
【发布时间】:2020-05-03 23:51:35
【问题描述】:

我对 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 函数中分配了 advertisingSet。 我应该在这里做什么?

【问题讨论】:

    标签: android bluetooth bluetooth-lowenergy beacon


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 非常感谢您的回复。即使调用了onAdvertisingSetStarted() 函数,currentAdvertisingSet[0] 也不会被分配。如果您能提供一些解决问题的说明,我真的很感激。再次感谢。
    • 我不认为这是一个真实的说法。我建议你在这一行设置断点currentAdvertisingSet[0] = advertisingSet; 或者添加一个调试行来打印它的值。我怀疑你会发现它确实有价值。
    • 由于旧模式在我的配置中是错误的,因此出现问题。我能够将currentAdvertisingSet[0].setAdvertisingData(new AdvertiseData.Builder().setIncludeDeviceName(true).setIncludeTxPowerLevel(true).build()); 放入一个单独的线程并在运行时成功更改广告数据。您的指示和建议对我的任务非常有帮助。我真的很感谢你的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多