0

我正在研究 BLE 信标与 Android 手机的距离估计。我开发了自己的基于 RSSI 的距离估计算法。(我将很快以库的形式推出距离计算算法)。为了计算,电话需要来自周围信标的大量广告包。

到目前为止,我已经使用 BLE 扫描的常规做法测试了代码。到目前为止,我已经编写了目标 API 级别 19 的代码。以下是我正在处理的代码的一部分,我开始扫描信标并在 10 秒后停止它。

private void scanLeDevice(final boolean enable) {
    if (enable) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                bluetoothAdapter.stopLeScan(LEScanCallback);
            }
        }, 10000L);

        bluetoothAdapter.startLeScan(LEScanCallback);
    }
}
private BluetoothAdapter.LeScanCallback LEScanCallback =
        new BluetoothAdapter.LeScanCallback() {
            @Override
            public void onLeScan(final BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord){   
                display(rssi);
                //append to an arrayList for further processing
            }
        };

目前我在 UI 线程上做大部分事情。我必须通过创建更多线程以以下方式实现功能。

  1. UI 线程应该不受所有计算或 LeScans 的影响。
  2. PacketReaderThread - 一个单独的线程,用于扫描数据包并继续将它们附加到 arrayList (我将在 arrayList 在算法中使用时清除不必要的数据)。与其在特定时间后停止扫描,我想无限期地保持扫描开启,以保持实时工作,只要应用程序正在运行。所以我可能会为此使用 IntentService。
  3. DistanceCalculatorThread(或 AsyncTask)- ArrayList 对象(包含扫描的数据包)将在此对象和 PacketReaderThread 之间同步,以获取/清除数据包并将距离计算通知给 UI。

我在Grepcode上看到了 BluetoothAdapter.LeScanCallback 的实现, 我有以下问题。

  1. BluetoothAdapter.LeScanCallback 是隐式绑定/绑定到主/UI 线程还是可移植到任何其他线程?
  2. 如果我将上面代码的两个实现都移动到其他线程,回调会在该线程上工作还是将绑定到 main/ui 线程?(因为我需要在单独的线程上进行数据包扫描,所以我需要了解 bluetoothAdapter.startLeScan(LEScanCallback) 和 BluetoothAdapter.LeScanCallback)
    (注意 - 我已经关注过这个问题,在那个问题中,答案寻求者本人声明回调已开启主线程,所以我没有得到实际答案。另外我看到了 altBeacon 规范并研究了他们的参考应用程序,它还使用 CycledScan 机制和 scan-stop-scanAgain 方式)
4

1 回答 1

1

的,Android 蓝牙扫描回调始终在主线程上进行。 4.x API 和 5+ API 都是如此。如果您正在对回调中的信息进行重要处理,那么明智的做法是按照您的描述将其传递给不同的线程。如果您不这样做,应用程序 UI 将变得迟钝,蓝牙处理甚至可能会备份,您将在日志中看到错误。

我不相信这在任何地方都有正式记录,但多年使用这些回调的经验始终表明这是真的。无法配置扫描,因此回调发生在不同的线程上。最佳实践是简单地对不同的线程进行一次调用以进行处理并快速退出回调。

这是在Android 信标库中完成的操作,如此处所示 请注意,回调的主体只是使用一个AsyncTask在后台线程上执行它的行:

new ScanProcessor(...).executeOnExecutor(mExecutor,
                    new ScanData(device, rssi, scanRecord));

此外,需要注意的是,虽然没有理由在较新的 Android 设备上停止扫描,但在某些较旧的设备上,如果信标广告可连接,则每个唯一的信标 MAC 地址只会获得一个回调。在这些设备上解决此问题的唯一方法是停止并重新启动扫描以获取额外的回调。

祝你的距离算法好运——如果你有好的结果并且有兴趣分享 Android 信标库,我很乐意讨论。

于 2016-07-08T13:50:23.073 回答