BLE 广告在 Android 中发生变化
BLE Advertisements changing in Android
我对 android 和 BLE 还很陌生。目前,我正在尝试通告一个数据包,该数据包会通过 BLE 在 android 中定期更改。我使用了 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 。
我需要在这里做什么?
显示的代码导致 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)
之类的检查来防止崩溃,但在显示的代码中,这永远不会成立,因此代码永远不会执行。
最终,您将需要移动更改广告集的代码,以便它在以后执行。您可以将这段代码放在回调中,但这对您的用例来说可能没有意义——开始广告然后立即将其更改为其他内容可能没有意义。
我对 android 和 BLE 还很陌生。目前,我正在尝试通告一个数据包,该数据包会通过 BLE 在 android 中定期更改。我使用了 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 。 我需要在这里做什么?
显示的代码导致 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)
之类的检查来防止崩溃,但在显示的代码中,这永远不会成立,因此代码永远不会执行。
最终,您将需要移动更改广告集的代码,以便它在以后执行。您可以将这段代码放在回调中,但这对您的用例来说可能没有意义——开始广告然后立即将其更改为其他内容可能没有意义。