BLE:通过 BluetoothAdapter#getRemoteDevice() 与扫描获取 BluetoothDevice

BLE: obtaining BluetoothDevice via BluetoothAdapter#getRemoteDevice() vs scanning

场景:

给定一个始终开启的设备,每秒进行一次低功耗蓝牙广告。
我必须为 Android 平板电脑实现一个应用程序,该应用程序通过低功耗蓝牙连接到此设备,发送一些命令然后断开连接。
最低 Android 版本:效果最好的版本,我可以自由决定。 我从 API 21 (Android 5.0, Lollipop)

开始

问题:

BLE 堆栈的问题也给我带来了麻烦:我想使用 BluetoothAdapter#getRemoteDevice(MACAddress: String)[=74= 检索到的对象发出成功的直接连接] 方法,它总是失败。

我的研究结果:

以下是我发现的似乎有用的问题/答案/帖子(也许这些会对某人有所帮助):

问题:

除此之外,我查看了 BluetoothDevice 的源代码,发现 connectGatt()[=74= 的 Context 参数] 方法 根本没有 使用:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java#1899
想知道这是否是 BLE 堆栈存在缺陷的原因之一?

此外,我不明白扫描仪检索到的 BluetoothDevice 对象与 BluetoothAdapter#getRemoteDevice(MACAddress:字符串) 方法。
如果我发出直接连接(autoconnect 参数在调用 connectGatt() 时设置为 false)设备通过扫描得到,连接通常会成功。但是,当使用 getRemoteDevice().

检索到的对象时,直接连接总是失败(status = 133,超时

由于我要连接的设备每秒都会进行自我宣传,因此我希望直接连接始终/大部分时间都能正常工作,就像在扫描的情况下一样。
因为后台连接(autoconnect 参数设置为 true)非常慢,我不能依赖它。
另外,由于扫描不可靠且速度慢,我不能在每次应用程序启动时都强制用户等待。

总结一下我的问题:

  • connectGatt()方法的Context参数根本没有使用-这可能是 BLE 堆栈存在缺陷的原因之一吗?我想有人把它放在那里是有充分理由的。
  • 扫描仪检索到的 BluetoothDevice 对象与 BluetoothAdapter#getRemoteDevice(MACAddress: String) 检索到的对象有什么区别方法?
  1. 上下文参数在早期的 Android 版本中使用过,但显然不再需要了。您仍然应该传递一个有效的上下文以与早期版本兼容,或者如果他们决定再次使用它则更新。

  2. 应该没有什么区别。但是如果你只是通过蓝牙设备地址连接,你会注意到 API 中的缺陷,你不能传递地址类型(public 或随机)。因此,如果您尝试连接到静态随机地址,除非您首先扫描了设备,否则可能会失败。这是因为 Android 保留了地址的缓存以及它在最新广告中的地址类型。因此,请尝试先扫描并确保您看到要连接的设备。然后尝试使用 BluetoothAdapter#getRemoteDevice(MACAddress: String).

  3. 进行连接