首页 > 解决方案 > 其他应用程序使我的 Android 应用程序的 BLE 扫描非常慢

问题描述

自从我相信 Nougat 以来,我的应用程序的 BLE 扫描性能似乎逐渐减慢。我现在可以回去在 Marshmallow 上进行测试,并确定那里不存在问题,但我在 Nougat 上没有设备了。我在 Pie 上的 Pixel 3a 严重显示了这个问题。

问题

当我的应用程序正在执行 BLE 扫描并且我正在寻找的设备就在我面前时,通常需要 30 - 60 秒,有时甚至更长时间,LE 扫描才会在 ScanCallback 中返回该设备。我的扫描代码非常简单:

private synchronized void startScan(@Nonnull BluetoothAdapter adapter, UUID[] serviceUuids) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        if (serviceUuids != null && serviceUuids.length > 0) {
            adapter.startLeScan(serviceUuids, BleScannerService.this);
        } else {
            adapter.startLeScan(BleScannerService.this);
        }
        broadcastUpdate(ACTION_SCAN_STARTED);
    } else {
        List<ScanFilter> filters = new ArrayList<>();
        if (serviceUuids != null && serviceUuids.length > 0) {
            for (UUID uuid : serviceUuids) {
                filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(uuid))
                        .build());
            }
        }
        BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
        if (scanner != null) {
            ScanSettings.Builder builder = new ScanSettings.Builder()
                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                    .setReportDelay(0);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                builder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
            }
            adapter.getBluetoothLeScanner().startScan(filters,
                    builder.build(),
                    mScanCallback);
            broadcastUpdate(ACTION_SCAN_STARTED);
        } else {
            mScanning = false;
        }
    }
}

该代码的很大一部分是指定已经是默认值的 ScanSettings,但我无能为力地尝试所有方法。所以我花了几天调试,终于在 logcat 中发现了一个非常有趣的模式。

每次在 ScanCallback 中找到设备时,我都会输出一个日志。当我的扫描第一次开始时,它只会每隔一两秒得到一个结果。我什至看到扫描结果之间需要 10 秒。正是在这段时间里,我的 BLE 设备没有被发现,大概是因为手机使用的任何巨大的扫描间隔都没有与 BLE 设备的广播间隔对齐。

然而,在某些时候它刚刚打开,我开始每秒得到很多结果,我的 BLE 设备马上就被找到了。我最终每次都在闸门打开的那一刻找到了这些日志(这是在派上):

2019-08-16 09:13:17.813 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 88:6B:0F:64:2F:D7
2019-08-16 09:13:28.087 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 88:6B:0F:64:2F:D7
2019-08-16 09:13:30.582 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:23:65:B7:D9:43
2019-08-16 09:13:33.024 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 00:07:80:CF:17:B9
2019-08-16 09:13:33.357 23338-23338/? D/BluetoothGatt: close()
2019-08-16 09:13:33.357 23338-23338/? D/BluetoothGatt: unregisterApp() - mClientIf=7
2019-08-16 09:13:33.363 23338-23338/? D/BluetoothManager: getConnectionState()
2019-08-16 09:13:33.363 23338-23338/? D/BluetoothManager: getConnectedDevices
2019-08-16 09:13:33.407 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:90:AC:1D:EF:38
2019-08-16 09:13:33.491 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:23:65:B7:D9:43
2019-08-16 09:13:33.524 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned F4:5C:89:90:C6:24
2019-08-16 09:13:33.625 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 46:54:BD:32:A2:EF
2019-08-16 09:13:33.708 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned F4:5C:89:90:C6:24
2019-08-16 09:13:34.374 23338-23338/? D/BluetoothGatt: connect() - device: C5:8B:66:21:90:5B, auto: true
2019-08-16 09:13:34.374 23338-23338/? D/BluetoothGatt: registerApp()
2019-08-16 09:13:34.374 23338-23338/? D/BluetoothGatt: registerApp() - UUID=35e43611-6c73-47a6-ad0d-9919df01108f
2019-08-16 09:13:34.378 23338-23480/? D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
2019-08-16 09:13:34.408 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:23:65:B7:D9:43
2019-08-16 09:13:34.424 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned F4:5C:89:90:C6:24
2019-08-16 09:13:34.492 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:90:AC:1D:EF:38
2019-08-16 09:13:34.592 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 6F:23:65:B7:D9:43
2019-08-16 09:13:34.608 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned F4:5C:89:90:C6:24
2019-08-16 09:13:34.658 27109-27109/<my package> E/<my app>: BleScannerService.java:275 onLeScan(): WPW: scanned 46:54:BD:32:A2:EF

所以 close() 完成的那一刻就是闸门打开的时候。还有一些其他应用程序持有 gatt 试图连接到某些东西,而当这种情况发生时,我的应用程序的扫描速度非常慢(也许 Android 会自动将其转换为 SCAN_MODE_OPPORTUNISTIC 或 SCAN_MODE_LOW_POWER 忽略我的 SCAN_MODE_LOW_LATENCY?)。

另一个始终存在的日志是“connect() - device: C5:8B:66:21:90:5B, auto: true”。我很幸运,能够在我手机的蓝牙设置中找到 C5:8B:66:21:90:5B……这是我的 Garmin GPS 手表!

原因

看起来,当我的手表关闭蓝牙或超出范围时,Garmin Connect 应用程序一直在扫描它(嗯,尝试使用自动标志连接),这就是导致我的 BLE 扫描非常缓慢地返回结果的原因。一旦连接超时,我的 BLE 扫描就会尖叫…… Garmin Connect 在我的 BLE 扫描期间会进行另一次连接,但我想现在我的扫描需要优先级并且它会一直保持很快,直到我取消它并重新开始它。然后它很慢,直到 Garmin 的连接再次超时。

我通过几种方式确认这是问题所在:

  1. 我卸载了 Garmin Connect。我的应用程序运行良好,每次都快速扫描。
  2. 我打开手表的蓝牙,让手机连接到它(因此不再试图找到它)​​。我的应用程序运行良好,每次都快速扫描。

回到 Marshmallow 上的手机,即使安装了 Garmin Connect 但手表未连接,上述问题也根本不会发生。我的假设是 Android 中发生了一些变化,导致一个应用程序的 connect() 干扰了另一个应用程序的 startScan()。在 Marshmallow 他们不会互相干扰,在 Pie 他们会。我猜它是从牛轧糖开始的,基于我读过的很多其他东西,但我无法证实。

有解决方案吗?

我不知道,但我希望有人在那里。据我所知,真的没有办法让你的应用程序“接管”蓝牙适配器或试图强迫自己比使用它的任何其他应用程序拥有资历(可以理解)。

有没有办法进行 BLE 扫描,以便它立即进入低延迟状态,而不管手机上发生了什么?它当然在棉花糖中起作用......

标签: androidbluetooth-lowenergy

解决方案


推荐阅读