BLE广告在Android中的变化

最后发布: 2020-07-09


问题

我对android和BLE很陌生。目前,我正在尝试宣传一个数据包,它在android系统中通过BLE定期变化。我使用了以下代码,它可以在 https:/source.android.comdevicesbluetoothble_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.但我已经把 广告集公共无效的onAdvertisingSetStarted。 函数,我需要在这里做什么?

android bluetooth bluetooth-lowenergy beacon
回答

所示的代码导致NullPointerException的原因是它试图访问的是 currentAdvertisingSet[0] 之前,你已经为该数组元素分配了一个值。

当代码用 final AdvertisingSet[] currentAdvertisingSet = new AdvertisingSet[1]; 然后数组的内容被初始化,每个元素都被设置为空。 这段代码并没有初始化 currentAdvertisingSet[0] 到一个非空值,直到 AdvertisingSetCallback 执行。 这是异步的,会在一段时间内发生。之后 号召 advertiser.startAdvertisingSet(...).

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

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

最终,你将需要移动改变广告集的代码,使其在以后的时间执行。 你可以把这段代码放在回调里面,但这对你的用例来说可能没有意义--启动广告然后立即把它改成别的东西可能没有意义。