Android 5.0.2 及更高版本不允许通过蓝牙 LE 进行 HID 访问

Posted

技术标签:

【中文标题】Android 5.0.2 及更高版本不允许通过蓝牙 LE 进行 HID 访问【英文标题】:Android 5.0.2 onwards don't allow HID access through Bluetooth LE 【发布时间】:2015-06-01 17:27:46 【问题描述】:

我的应用运行良好,直到 android 5.0.2 不允许第三方应用通过低功耗蓝牙连接到 HID 设备。

myGatt.setCharacteristicNotification(gattChar, true);

06-01 17:39:35.356: W/BluetoothGatt(21599):
java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission:Neither
user 10157 nor current process has android.permission.BLUETOOTH_PRIVILEGED.

<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />

BLUETOOTH_PRIVILEGED 权限不适用于第三方应用。它仅适用于系统或制造商应用程序。

Android 注意的最新变化: 对 HID-over-GATT 实施 BLUETOOTH_PRIVILEGED 权限 https://android.googlesource.com/platform/packages/apps/Bluetooth/+/02bebee

Code snippet:

private static final UUID[] HID_UUIDS = 
    UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
    UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
    UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
    UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB") ;

if (isHidUuid(charUuid)) enforcePrivilegedPermission();

我的问题:有没有办法覆盖 HID_UUIDS 或强制执行PrivilegedPermission?我可以使用反射来绕过它吗?

Android 每次发布新版本,都会破坏之前的代码。

谢谢!

【问题讨论】:

【参考方案1】:

这个问题很老了,但仍然值得回答。 HID(和 FIDO https://fidoalliance.org/)服务受到保护,确实需要系统权限 source。只有使用系统密钥签名的应用程序才能使用此服务,也就是蓝牙设置。这是为了确保第 3 方应用程序无法收听无线键盘上键入的键,因为所有通知和指示都会传输到所有 BluetoothGatt 对象。如果没有这种保护,您将能够连接到 HID 设备(您仍然可以),使用 gatt.setCharacteristicNotification(.., true) 启用通知并在键入密钥时接收更新。有了一点关于报告特性的知识,你就可以得到所有的键和鼠标位置,包括密码等。所以这不是一个中断,而是一个错误修复。在 KitKat 上,您仍然可以这样做。

唯一的解决方案是编译您自己的 AOSP Android 版本并使用相同的密钥对您的应用进行签名。否则,这将是无用的保护。

顺便说一句,从 Android 8 或更早版本开始,您不会收到 SecurityException。该调用只返回 true ,就好像任何其他调用一样,并且您永远不会收到任何回调。 此处可能已更改:https://android.googlesource.com/platform/packages/apps/Bluetooth/+/32dc7a6b919375aede777f3c821fa316d85449ae%5E%21/#F2

【讨论】:

我发布了一个类似的问题,想知道是否有明确答案的来源,为什么蓝牙 LE HID 有权限,而蓝牙经典版没有?我正在尝试通过 Android 应用程序为输出和输入报告设置连接,但写入特征永远无法到达回调。似乎令人惊讶的是,没有人找到一种“hacky”的方式来实现这项工作。让我知道你的想法。

以上是关于Android 5.0.2 及更高版本不允许通过蓝牙 LE 进行 HID 访问的主要内容,如果未能解决你的问题,请参考以下文章

如何在android Pie及更高版本中以编程方式通过拨号器拨打电话

Android 6 及更高版本中的 Android SSLSocket 握手失败

为啥在 Android Q 及更高版本上不需要 WRITE_EXTERNAL_STORAGE

pulltorefresh android 4.1及更高版本[重复]

错误:Android Gradle 插件仅支持 Kotlin Gradle 插件版本 1.3.0 及更高版本

如何以编程方式在 Android(KitKat 及更高版本)中添加 APN