我看到BluetoothSocket可以是TYPE_L2CAP类型,但BluetoothSocket的构造函数似乎是私有的,我只能找到一种方法来实例化RFCOMM类型的socket。如何获取和使用L2CAP socket?Android是否支持它?
我看到BluetoothSocket可以是TYPE_L2CAP类型,但BluetoothSocket的构造函数似乎是私有的,我只能找到一种方法来实例化RFCOMM类型的socket。如何获取和使用L2CAP socket?Android是否支持它?
更新于2019年10月
支持已经到位!享受新的API吧:
更新 03/2019 第一个Android Q beta版已经发布,看起来支持即将到来。 https://developer.android.com/sdk/api_diff/q-beta1/changes.html
更新 10/2018
得到消息说从Android Q开始将支持L2CAP CoC。
不幸的是,我无法引用官方来源。
旧回答
我会发布自己的结果,希望能帮助其他人,也许会得到提示,如果我漏掉了什么。
TL;DR:看起来我不能
没有公共API可以获得L2CAP CoC套接字
这个 Android 文档页面声称自 Android 8.0 起提供了“LE 连接导向通道”(l2cap 通道)。在 Android API 中,有一个 BluetoothSocket
类可以具有类型 L2_CAP
。但是,由于该类的元素是私有可见性的,因此无法获取具有此类型的 BluetoothSocket 实例。这就是 Android 公共 java API 的局限所在。
那怎么办?
深入挖掘公共 java API 的表面下。Android 版本 8+ 的源代码提供了一种正在不断发展的 l2cap socket 获取方式:
createL2capSocket
方法(来源)createL2capCoCSocket
方法(来源)createL2capChannel
方法(我猜是未来的版本)(来源)但是在每个发布的版本中,这些代码都被标记为@hide
注释,这意味着这些方法实际上不能使用。
在Android 9之前,隐藏的方法至少可以通过Java反射在某些设备上访问。这就是我们如何能够在Android 8上进行测试的原因,但效果很差。
自从操作系统的第9个版本以后,这已经不再可能了:平台积极阻止尝试非法访问API。
此外...
除了实例化套接字的方法不可见之外,还有证据表明API的不成熟也体现在缺乏调整l2cap连接参数的方法上。
走本地化路线?
我没有使用NDK的经验,但我认为可以编写C代码来利用隐藏方法使用的相同低级功能。除非Android也阻止了这种使用方式,这很可能。此外,这种使用方式会与手机上蓝牙堆栈的常规使用冲突:正常使用通常都是由Android服务过滤的。绕过这个服务会导致不可预测的后果,不适合生产应用程序。
总结一下
在Android 8.1上使用反射进行测试结果非常不令人满意。尽管做出了努力,“LE Connection-Oriented Channels”自Android 8.0以来可用的说法仍无法得到确认。
在较新的版本中,创建L2CAP通道的隐藏方法正在发展演变,并且最近已经移除了隐藏注释。很难确定这意味着我们需要多长时间才能拥有支持此API的设备。很可能需要数年时间,L2CAP通道才能可靠地提供给大量的Android用户使用。
read(byte[])
会报告数据包的长度为-1而不是0。 - EmilBluetoothDevice.createInsecureL2capChannel(int)
方法在应用程序端创建套接字,但是遇到了IOException异常。有人对此有什么想法吗? - Harshvardhan Trivedi