无限Android BLE扫描BLE-Beacon数据包

时间:2016-07-08 12:19:53

标签: android android-bluetooth altbeacon android-ibeacon google-beacon-platform

我正在研究Android手机中BLE Beacons的距离估算。我已经开发了自己的基于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中删除不必要的数据)。我不想在一定时间后停止扫描,而是希望保持扫描无限时间,以便在app运行时保持实时工作。所以我可能会使用IntentService。
  3. DistanceCalculatorThread(或AsyncTask) - ArrayList对象(包含已扫描的数据包)将在此与PacketReaderThread之间同步,用于获取/擦除数据包,并通知UI的距离计算。
  4. 我在Grepcode上看到了BluetoothAdapter.LeScanCallback的实现 我有以下问题。

    1. BluetoothAdapter.LeScanCallback是否隐式绑定/绑定到主/ UI线程,还是可以移植到任何其他线程?
    2. 如果我将上述代码的两个实现移动到其他某个线程,那么回调是否会在该线程上运行,或者它是否会绑定到main / ui线程? (由于我需要在单独的线程上进行数据包扫描,我需要了解bluetoothAdapter.startLeScan(LEScanCallback)和BluetoothAdapter.LeScanCallback) (注意 - 我已经关注this question,在那个问题中,答案寻求者自己说回调是在主线程上,所以我没有得到实际答案。我也看到了altBeacon规范并研究了他们的参考应用程序,它还使用CycledScan机制和scan-stop-scanAgain方式)

1 个答案:

答案 0 :(得分:1)

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

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

这是Android Beacon Library中显示的内容here.注意,回调的主体只使用AsyncTask并在后台线程上执行此行:

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

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

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