BLE Реклама меняется в Android - PullRequest
0 голосов
/ 03 мая 2020

Я очень новичок в 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. Но я уже назначил AdvertisingSet в publi c void onAdvertisingSetStarted . Что мне нужно сделать здесь?

1 Ответ

0 голосов
/ 03 мая 2020

Причина, по которой указанный код вызывает исключение 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), чтобы предотвратить взлом sh, но в показанном коде это никогда не будет верным, поэтому код никогда не будет выполнен.

В конечном итоге вам необходимо переместить код, который изменяет рекламный набор, чтобы он выполнялся позднее. Вы можете поместить этот код в обратный вызов, но это может не иметь смысла для вашего варианта использования - скорее всего, нет смысла начинать рекламу, а затем немедленно менять ее на что-то другое.

...