如何在安卓中实例化一个L2Cap套接字?

7

我看到BluetoothSocket可以是TYPE_L2CAP类型,但BluetoothSocket的构造函数似乎是私有的,我只能找到一种方法来实例化RFCOMM类型的socket。如何获取和使用L2CAP socket?Android是否支持它?

1个回答

9

更新于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 获取方式:

  • 在Android 8中有一个createL2capSocket方法(来源)
  • 在Android 9中有一个createL2capCoCSocket方法(来源)
  • 在Android项目的主分支中有一个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用户使用。

1
传输速度很慢,连接也不稳定。希望我能很快用 Q 进行测试。 - nsndvd
2
我刚在Android Q beta上进行了测试。看起来效果不错。我也在Oreo上进行了测试,但是传输速度很慢,因为它只允许一次只传输1个credit,所以每个连接事件最多只能传输1个数据包。然而,两个版本都存在一个错误,即如果您向Android发送长度为0的数据包,则read(byte[])会报告数据包的长度为-1而不是0。 - Emil
1
也许你可以用你的最新结果更新我的答案 ;) - nsndvd
我有一个Python脚本,在Linux上创建L2CAP服务器,并使用BluetoothDevice.createInsecureL2capChannel(int)方法在应用程序端创建套接字,但是遇到了IOException异常。有人对此有什么想法吗? - Harshvardhan Trivedi
@HarshvardhanTrivedi 不是很清楚,能提供一下堆栈跟踪吗? - nsndvd
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接