我对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。 函数,我需要在这里做什么?
所示的代码导致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)
来防止崩溃,但在所示的代码中,这永远不会是真的,所以代码永远不会执行。
最终,你将需要移动改变广告集的代码,使其在以后的时间执行。 你可以把这段代码放在回调里面,但这对你的用例来说可能没有意义--启动广告然后立即把它改成别的东西可能没有意义。