【问题标题】:Decreased BLE startScan detected devices on Android 5.0 Lollipop在 Android 5.0 Lollipop 上减少了 BLE startScan 检测到的设备
【发布时间】:2015-01-22 13:08:04
【问题描述】:

短版:

在我对 Android 5.0 Lollipop 的测试中,我注意到android.bluetooth.le.BluetoothLeScanner 检测 BLE 设备的频率低于 Android 4.4 KitKat。为什么会这样,还有其他选择吗?

长版:

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

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

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
        }
    };

}

基本上这给了我所需的结果,但这个过程非常耗费资源,并最终导致蓝牙适配器无响应。

出于这些原因,我将我的 Nexus 7 升级到了 Android 5.0 Lollipop,看看我的 BLE 问题是否会得到解决。在 Lollipop 中,BluetoothAdapter.startLeScan(LeScanCallback) 已被弃用,取而代之的是a new API,它允许对扫描过程进行更多控制。从我的第一次测试来看,当 RSSI 值发生变化时,startScan 似乎不会持续调用我的回调(在我的 Nexus 7 上),所以我仍然需要使用 startScan / stopScan 实现:

@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 秒显示一次相同的信标。

您知道造成这种差异的原因是什么吗?我错过了什么,也许是一些新的设置?是否有其他方法可以执行上述操作?

提前非常感谢!

亚伯

PS:我想包含更多指向我使用过的资源的链接,但我还没有代表点。

【问题讨论】:

  • 在 Lollipop 中“当 RSSI 值发生变化时,startScan 不会连续调用我的回调(在我的 Nexus 7 上)”。但它是至少每隔一段时间再次调用一次还是只调用一次?抱歉,我没有要测试的 Nexus 7。在我的 Nexus 5 中,它会在 SCAN_MODE_LOW_POWER 中每秒被调用一次。
  • @abelcookingfox 我几乎得到了和你一样糟糕的结果,我使用的是一加一,CM ROM 5.0.2,有时扫描调用超过 30 秒,但有时它就像死的。你现在有什么解决办法吗?
  • 我重做了测试,我的一加一手机只扫了2次,就再也不会触发回调了。
  • “不幸的是,我每 15 - 30 秒检测一次信标,而 KitKat 版本在此扫描间隔内每 1 - 2 秒向我显示相同的信标”你是什么意思 - 这意味着你有 5 个标签,在 Android 4 中,您会为每个信标以 1-2 间隔获得一个回调,而在 Android 5 中,间隔是 15-30 秒还是什么?

标签: bluetooth-lowenergy android-5.0-lollipop rssi ibeacon-android android-ibeacon


【解决方案1】:

在运行新的 Android 5.0 扫描 API 的 Nexus 5 上,我得到了非常不同的结果。使用 SCAN_MODE_LOW_LATENCY 时,BLE 数据包的检测几乎是实时的,对于以 10Hz 传输的 BLE 信标,每 100 毫秒。

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

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

这些测试基于运行开源 Android Beacon Library 2.0 的实验性 android-l-apis 分支 here

您的测试结果有何不同并不明显,但开始和停止扫描可能会改变结果。

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

【讨论】:

  • 感谢您的建议,@davidgyoung!有任何关于这种情况的更新吗? :)
  • 我无法重现你描述的症状,所以除了上面描述的以外,我什么都不知道。
  • 嗨,大卫,您能帮我在使用服务的 android 设备中的蓝牙的 lescan 中添加扫描间隔。
  • @johny-kumar,请发布一个新问题
  • 这里是我的问题的网址stackoverflow.com/questions/28215216/…
【解决方案2】:

我还没有 50 的评论声望,所以请耐心等待,这个评论将以答案的形式出现。在您的代码中,这部分不应该是:

if (isScanning) { scanner.startScan(...)

改为:

if (!isScanning) {
 scanner.startScan(...)

因为遵循您的代码,您在开始扫描之前调用了 stopScan()。如果 stopScan() 方法是幂等/安全的,它可能不会对结果产生直接影响。但是您知道,为了代码的可理解性,您应该编辑问题。对你的代码做同样的事情,有时拜占庭的事情在起作用;)

您是否尝试过更大的 SCAN_INTERVAL_MS 值?如果有,有多大?

【讨论】:

  • 谢谢,我已经编辑了我的问题。我的代码是正确的。 :) 是的,我尝试了高达 1000 毫秒的扫描间隔,但这只是意味着您获得扫描结果的频率较低。当使用小于 200 的扫描间隔时,蓝牙适配器并不总是能够检测到设备。
【解决方案3】:

我的 Nexus 4 在 KitKat 和 Lollipop 中都体验到了非常相似的结果。

使用 KitKat 时,蓝牙适配器最终也无响应;起初我认为它可能与较短的扫描间隔(200ms)有关,但将该数字增加到甚至一秒钟并没有帮助,在这件事上,我发现,当以编程方式禁用和启用适配器时,有时可以解决问题.不幸的是,我不能说它一直有效。

现在有了 Lollipop,我寄予厚望解决这个问题,我遇到了与您描述的相同的行为。我还必须使用 startScan / stopScan 实现,在检测时间方面得到类似的结果。遗憾的是,我还没有找到更快获得结果的解决方法。

根据您的描述,我认为这可能是硬件问题,尽管 Nexus 7 和 Nexus 4 来自不同的制造商(华硕和 LG)。

我知道除了试图回答您关于您遗漏某些东西的问题之外,我在这里并没有提供太多帮助;我不这么认为,我认为问题出在硬件或蓝牙 API 之类的东西上,但它在不同设备上的行为仍然不尽如人意。

【讨论】:

  • 谢谢,@marp。现在我将继续使用 startScan / stopScan 程序。
【解决方案4】:

超过 API 21 android 默认使用 SCAN_MODE_LOW_POWERSCAN_MODE_LOW_POWER

试试 SCAN_MODE_BALANCED 看看会不会好转。
SCAN_MODE_BALANCED

【讨论】:

    【解决方案5】:

    如果您在 google 上搜索BW13_DayOne_Session1 Bluetooth Advanced,您将找到一个 pdf 文档,该文档根据发现设置为您提供了设备的延迟(参见第 8 页)。我猜你的问题与这些时间有关。您可以通过确定您正在测试的设备的广告配置(Adv Int、占空比)来进行验证,然后确定 API 设置在配置扫描间隔等方面所做的工作。一旦有了这些,您就可以使用该表进行插值以查看您是否获得了预期的结果。

    我知道这是一个软件站点,但通常在与硬件交互时,您需要了解协议,否则您会在黑暗中拍摄。

    【讨论】:

    • 你能发布那个pdf吗?我找不到它。
    • 该搜索词的唯一谷歌点击是这个页面和它的镜像!
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多