Android BLE onScanResult 从未在 Android 11 的后台调用。正在处理 Android 10

Android BLE onScanResult is never called in the background on Android 11. Was working on Android 10

我有一个应用程序可以扫描 BLE 设备。它 在 Android 10 上完美运行,但自从我将 phone 更新为 Android 11,如果我将应用程序置于 后台,或者如果我锁定屏幕,onScanResult 永远不会被调用

这很烦人。我还没有找到任何可能导致这种情况的合理想法。我没有在 Android 11 中发现任何表明这种行为改变的差异。 Android 12 有新的 BT 权限,如果你将你的应用定位到 api 级别 31,但我确实将我的目标定位到 api 级别 30,我做到了 运行 我的应用在 Android 11.

我真是一头雾水。 我尝试了不同的扫描模式,也尝试了添加扫描过滤器,但没有任何改变。

我的扫描设置:

ScanSettings ss = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).build();
        List<ScanFilter> filterList = new ArrayList<>();
        filterList.add(new ScanFilter.Builder().setManufacturerData(Constants.HARDWARE_MANUFACTURER_ID, new byte[]{}).build());
        BluetoothUtil.getBluetoothLeScannerInstance().startScan(filterList, ss, leScanCallback);

到目前为止,我遇到了以下情况:

当应用程序在前台且设备屏幕未锁定时,onScanResult 调用完美。一旦我将应用程序推到后台或锁定屏幕,我就不再收到 onScanResult

的任何回调

这是应用程序在前台而不是锁定屏幕时的示例日志:

15:47:15 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:47:17 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:21 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:21 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:22 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:22 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:47:25 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:47:25 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:26 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:26 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:29 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:30 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:30 com.myapp.co I/SCANNED_: onScanResult ran!
15:47:32 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)

以及应用程序处于后台和/或锁定屏幕时的示例日志:

15:48:25 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:48:32 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:48:35 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:48:42 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:48:45 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:48:52 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:48:55 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:49:02 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:49:05 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:49:12 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:49:15 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:49:22 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:49:25 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:49:32 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)
15:49:35 com.myapp.co I/BL_START: ...Starting BL scan. (Start of current window)
15:49:42 com.myapp.co I/BL_STOP: ...Finishing BL scan. (End of current window)

如您所见,当应用程序位于前台且屏幕未锁定时,onScanResult 会正常调用。

什么可能导致这种情况,我该如何防止这种功能?

根据所提供的信息很难说清楚,但一个原因可能是 Android 11 需要清单中的“后台位置访问”才能在后台模式下工作。

您可以在这里查看更多详细信息: https://developer.android.com/about/versions/11/privacy/foreground-services

确保您的应用定义了 BLE 扫描的所有强制性权限。这些权限要求会随着时间的推移而发生变化,因此您必须小心地将它们全部放在您的 AndoroidManifest:


<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

<!-- Bluetooth permissions for BLE scanning -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

<!-- Location permissions for BLE scanning -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

还要确保

  • 不仅您的应用已授予 ACCESS_FINE_LOCATION
  • 权限
  • 而且您在 OS 级别启用 LocationServices:

如果您使用 Service 扫描设备,请确保此服务已正确定义为前台服务。这个主题太大了,只能抽出一个代码片段。有点reading the documentation。但是这里的文档很好,所以你应该没问题。

我在 Android 11 遇到了同样的问题。我会解释我所做的,希望它能帮助你和遇到同样问题的人。

首先,正如我提到的,请确保您拥有 BLE 扫描的所有强制权限。

其次,转到您的物理 Android 设备并确保该应用程序未包含在“优化电池使用”应用程序中,如果是,请将其从那里删除并再次测试代码。

最后,所有这些选项都没有帮助解决我的问题。这和你的一样。当我尝试使用此扫描设置扫描 BLE 设备时:

 BluetoothAdapter.DefaultAdapter.BluetoothLeScanner.StartScan(scanFilters, scanSettingsBuilder.Build(),
                _customScanCallback);

我的前台服务在前台、后台都能正常工作,但 phone 被锁定时就不行了。原因,回调从未被调用过。我所做的工作是解决问题。它可能不是最好的解决方案,但它正在工作。 使用 public static BluetoothAdapter Adapter => BluetoothAdapter.DefaultAdapter; 然后调用 Adapter.StartDiscovery(); 换句话说,在没有 BluetoothLEScanner 对象的情况下尝试它。然后在 OnReceive() 方法中从作为参数传递的意图对象中提取所有需要的信息。这是 Android 11 设备锁定时我的输出片段。 p.s 如果您发现使用 BluetoothLeScanner 对象的更好方法,请告诉我 .

显然,Android11 中存在错误。如果您同时请求两个位置权限,则不会弹出权限对话框。你得一一问他们。

错误在 android 11 中。 你需要一一询问。