减少BLE startScan在Android 5.0 Lollipop上检测到的设备 [英] Decreased BLE startScan detected devices on Android 5.0 Lollipop

查看:100
本文介绍了减少BLE startScan在Android 5.0 Lollipop上检测到的设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短版本:

在使用Android 5.0 Lollipop进行测试时,我注意到 android.bluetooth.le.BluetoothLeScanner 探测BLE设备的频率低于Android 4.4 KitKat。为什么会这样,还有替代方法吗?

In my tests with Android 5.0 Lollipop I have noticed android.bluetooth.le.BluetoothLeScanner detects BLE devices less frequently than Android 4.4 KitKat. Why is this and is there an alternative?

长版:

我正在开发Android应用程序,特别是Nexus 7平板电脑专用,主要用于检测低功耗蓝牙(BLE)设备。该应用程序主要对信标的RSSI值感兴趣,以确定它们与平板电脑的接近程度。这意味着我不需要连接到BLE设备,因为当检测到设备时RSSI值会传递到扫描回调。

I am developing an Android application, specifically for the Nexus 7 tablet, that focuses on detecting Bluetooth Low Energy (BLE) devices. The app is mainly interested in the RSSI value of the beacons, to determine their proximity to the tablet. This means I won't need to connect to the BLE device, since the RSSI value is passed to the scan callback when the device is detected.

在Android 4.4 KitKat中,当我调用 BluetoothAdapter.startLeScan(LeScanCallback)时,对于每个检测到的BLE设备,我的回调仅被调用一次。 (我已经看到一些讨论声称此行为可能因设备而异)但是,我对不断变化的RSSI值感兴趣,因此当前推荐的方法是以设置的间隔(在我的情况下为250ms)连续执行startLeScan和stopLeScan:

In Android 4.4 KitKat, when I call BluetoothAdapter.startLeScan(LeScanCallback), my callback gets called only ONCE for every detected BLE device. (I have seen some discussions claim that this behaviour can differ per device) However, I am interested in the constantly changing RSSI value, so the currently recommended way is to continuously do startLeScan and stopLeScan with a set interval (250ms in my case):

public class TheOldWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private boolean isScanning = false;

    public void beginScanning() {
        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();

            if (isScanning) {
                adapter.stopLeScan(leScanCallback);
            } else if (!adapter.startLeScan(leScanCallback)) {
                // an error occurred during startLeScan
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            // use the RSSI value
        }
    };

}

基本上,这给了我所需的结果,但是这个过程是

Essentially this gives me the required results, but this process is very resource intensive and eventually leads to an unresponsive bluetooth adapter.

由于这些原因,我将Nexus 7升级到了Android 5.0 Lollipop,以查看BLE问题是否可以解决。在Lollipop中,BluetoothAdapter.startLeScan(LeScanCallback)已被弃用并替换为新的API 允许对扫描过程进行更多控制。从我的第一个测试来看,当RSSI值更改时,startScan似乎并没有连续调用我的回调(在Nexus 7上),因此我仍然需要使用startScan / stopScan实现:

For these reasons I upgraded my Nexus 7 to Android 5.0 Lollipop, to see whether my BLE issues would be fixed. In Lollipop BluetoothAdapter.startLeScan(LeScanCallback) is deprecated and replaced with a new API that allows for some more control over the scanning process. From my first tests, it appears startScan does not continuously call my callback (on my Nexus 7) when the RSSI values change, so I still need to use the startScan / stopScan implementation:

@TargetApi(21)
public class TheNewWay {

    private static final int SCAN_INTERVAL_MS = 250;

    private Handler scanHandler = new Handler();
    private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>();
    private ScanSettings scanSettings;
    private boolean isScanning = false;

    public void beginScanning() {
        ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
        scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        scanSettings = scanSettingsBuilder.build();

        scanHandler.post(scanRunnable);
    }

    private Runnable scanRunnable = new Runnable() {
        @Override
        public void run() {
            BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();

            if (isScanning) {
                scanner.stopScan(scanCallback);
            } else {
                scanner.startScan(scanFilters, scanSettings, scanCallback);
            }

            isScanning = !isScanning;

            scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
        }
    };

    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            int rssi = result.getRssi();

            // do something with RSSI value
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);

            // a scan error occurred
        }
    };

}

如您所见,我已经使用ScanSettings类,可用于设置 scanMode 。我使用 ScanSettings.SCAN_MODE_LOW_LATENCY ,该文件包含以下文档:使用最高占空比进行扫描。建议仅在前台运行应用程序时才使用此模式。听起来完全像我想要的,但是不幸的是,我每15到30秒只能检测到一个信标,在此扫描间隔内,KitKat版本每1-2秒钟就会向我显示相同的信标。

As you can see, I have configured the scanner using the ScanSettings class, which allows you to set the scanMode. I use ScanSettings.SCAN_MODE_LOW_LATENCY, which has the following documentation: "Scan using highest duty cycle. It's recommended to only use this mode when the application is running in the foreground." Sounds exactly like what I want, but unfortunately I only get a beacon detect every 15 - 30 seconds, where the KitKat version shows me the same beacon every 1 - 2 seconds on this scan interval.

您是否知道造成这种差异的原因是什么?我是否缺少某些内容,也许有一些新设置?有其他替代方法可以做到这一点吗?

Do you have any idea what could be the reason for this difference? Am I missing something, maybe some new settings? Are there alternative ways of doing the above?

多谢!

Abel

PS:我想包括更多我所使用资源的链接,但我现在还没有代表点。

PS: I wanted to include more links to resources I've used, but I don't have the rep points for it yet.

推荐答案

使用运行新的Android 5.0扫描API的Nexus 5,我获得了截然不同的结果。使用SCAN_MODE_LOW_LATENCY时,BLE信标以10Hz传输的每100ms几乎实时地检测到BLE数据包。

I have gotten very different results with a Nexus 5 running the new Android 5.0 scanning APIs. Detections of BLE packets came in at near real time when using SCAN_MODE_LOW_LATENCY, at every 100ms for BLE beacons transmitting at 10Hz.

您可以在此处阅读完整结果:

You can read the full results here:

http:/ /developer.radiusnetworks.com/2014/10/28/android-5.0-scanning.html

这些测试基于运行开源Android信标库2.0的实验性android-l-apis分支此处

These tests are based off of running the open source Android Beacon Library 2.0's experimental android-l-apis branch here.

测试结果之间的区别并不明显,但是开始和停止扫描可能会改变结果。

It is not obvious what the difference is in your test results, but it is possible that starting and stopping scanning is changing the results.

编辑::可能是硬件有所不同。在Nexus 4上查看类似计时的报告: https:// github.com/AltBeacon/android-beacon-library/issues/59#issuecomment-64281446

it is possible the hardware is the difference. See a report of similar timings on the Nexus 4: https://github.com/AltBeacon/android-beacon-library/issues/59#issuecomment-64281446

这篇关于减少BLE startScan在Android 5.0 Lollipop上检测到的设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆