我们有一个可编程的设备,我们正在工作,通过设备的名称输出数据。该设备运行正常,可以看到使用类似nrf connect的应用程序正确更改名称。然而,我们在自己的android应用程序中也很难做到这一点。我们可以很好地检测到这些设备,但它们几乎永远不会超过最初的名称。
我开始使用的代码有一个循环,该循环在onresume()中启动,该循环使用bluetoothlescanner和startscan()函数进行扫描。
public void BLEScan(final boolean enable){
final int SCAN_PERIOD = 12000;
final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
if (enable) {
Log.d(TAG, "Starting Scan");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
BLEScan(false);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
bluetoothLeScanner.flushPendingScanResults(mLeScanCallback);
bluetoothLeScanner.startScan(mLeScanCallback);
} else {
Log.d(TAG, "Stopping Scan");
bluetoothLeScanner.flushPendingScanResults(mLeScanCallback);
bluetoothLeScanner.stopScan(mLeScanCallback);
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
BLEScan(true);
}
}, SCAN_PERIOD);
}
}
在mlescancallback中检测到基于设备的过滤器。基本上,如果它以前没有见过设备,它会将其添加到信标列表中。但是,如果它以前看到过它,它会使用beacon的seen()函数更新值,并使用beacon的名称seen,因为这是信息的来源。在这两种情况下,它都将更新其适配器以填充新信息。
private ScanCallback mLeScanCallback =
new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
final ScanResult res2 = result;
runOnUiThread(new Runnable() {
@Override
public void run() {
BluetoothDevice device = res2.getDevice();
String address = device.getAddress();
if (device.getName() != null){
if (device.getName().contains("ABT:")){
if (!mLeBeacons.containsKey(address)){
BleBeacon beacon = new BleBeacon(device.getName(), address);
bleList.add(beacon);
adapter.notifyDataSetChanged();
mLeBeacons.put(device.getAddress(), beacon);
} else {
for (int x = 0; x < bleList.size(); x++){
if (device.getAddress().equals(bleList.get(x).getMAC())){
bleList.get(x).seen(device.getName());
adapter.notifyDataSetChanged();
}
}
}
}
}
}
});
}
};
但是,即使在更新名称之后,mlescancallback也只会返回原始名称。
在这里搜索了一段时间后,我不断发现的是使用函数fetchuuidswithsdp()和意图,如action\u found、action\u uuid、action\u discovery\u finished和action\u name\u changed,以查看名称的正确更改。所以,我将fetchuuidswithsdp()添加到mlescancallback中。然而,虽然这会触发意图,但名称仍然没有更新。我试着按实际意图调用fetchuuidswithsdp(),但也没有用。奇怪的是,如果我关掉手机屏幕或者离设备足够远的话,改变名字的动作偶尔会触发。但是,onpause()所做的只是调用 super.onPause()
以及 BLEScan(false)
. 而且,由于这些都是我在循环中已经在做的事情,所以我不知道如何在代码处于唤醒状态时将其引入代码中。
在进一步搜索之后,我发现,要使用fetchuuidswithsdq()函数,需要使用bluetoothadapter的startdiscovery()函数。所以,我把blescan改成了使用它,完全去掉了mlescan回调。
public void BLEScan(final boolean enable){
final int SCAN_PERIOD = 12000;
if (enable) {
Log.d(TAG, "Starting Scan");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
BLEScan(false);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
if (mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
} else {
Log.d(TAG, "Stopping Scan");
mBluetoothAdapter.cancelDiscovery();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
BLEScan(true);
}
}, SCAN_PERIOD);
}
}
然而,虽然意图在以前被触发,但现在却没有,即使它们在我的意图过滤器中。在做了更多的搜索之后,我发现有人说startdiscovery()不适用于le设备。所以,我搜索了你应该用的东西…这让我一路回到了蓝牙扫描的startscan。在那一刻,我意识到我已经在一个圈子里,需要帮助。
我回顾了我的整个过程,因为,在这个过程中,我遗漏了一些东西。我只是不知道它在哪里。我应该使用startscan()吗?我没有正确使用startdiscovery()吗?或者有什么我应该完全使用的东西吗?事实上,action\u name\u偶尔会被更改,这让我想回到这个问题上,但是如何让它在设备处于唤醒状态时一直工作呢?
2条答案
按热度按时间ctehm74n1#
虽然我没有在我的原始代码中发现我做错了什么(尽管听起来android可能只是在这方面被打破了),但我确实找到了一个解决方法。nrf的nfc工具箱有可用的源代码,并通过添加的过滤器进行批量扫描,还有它自己的北欧图书馆的le扫描仪。现在我的扫描功能是这样的:
我的回电是这样的:
这似乎起了作用。不过,您需要将以下内容添加到依赖项中。
在那之后,我的名字动作\u名字\u改变意图被正确触发并且数据被更新。
我不确定这是从结果中检索名称的不同方式,还是批量扫描。但是,如果北欧不使用标准的android ble库,我猜这是最好的方法。
k97glaaz2#
我想你可能只是在android上缓存有问题。请在此处查看此答案以获取可能的解决方案:https://stackoverflow.com/a/50745997/7473793