如何在 Android 中实例化 L2Cap 套接字?

Posted

技术标签:

【中文标题】如何在 Android 中实例化 L2Cap 套接字?【英文标题】:How can I instantiate a L2Cap socket in Android? 【发布时间】:2019-01-07 22:19:21 【问题描述】:

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

【问题讨论】:

【参考方案1】:

2019 年 10 月更新

支持!享受新的 API:

BluetoothDevice.createL2capChannel(int) BluetoothDevice.createInsecureL2capChannel(int) BluetoothAdapter.listenUsingL2capChannel() BluetoothAdapter.listenUsingInsecureL2capChannel()

2019 年 3 月更新 随着第一个 Android Q 测试版的出现,支持似乎终于到来了。 https://developer.android.com/sdk/api_diff/q-beta1/changes.html

2018 年 10 月更新

得知从 Android Q 开始将支持 L2CAP CoC。

很遗憾,我无法为此引用官方来源。

老答案

我会发布我自己的结果,希望可以帮助其他人,如果我遗漏了什么,也许会得到提示。

TL;DR:看来我做不到

无法通过公共 API 获得 L2CAP CoC 套接字

Android 文档中的This 页面声称“LE Con​​nection-Oriented Channels”(l2cap 通道)自 Android 8.0 起可用。 在 Android API 中有一个 BluetoothSocket 类,它的类型可以是 L2_CAP。但是由于该类元素的私有可见性,无法获得具有这种类型的 BluetoothSocket 实例。 public Android java API 就是这样:卡住了。

那么?

挖掘公共 java API 的表面。 android 8+ 版本的源代码提供了一种获取随时间演变的 l2cap 套接字的方法:

android 8 中的 createL2capSocket 方法 (source) android 9 中的 createL2capCoCSocket 方法 (source) android 项目主分支中的createL2capChannel(我猜是未来版本?)(source)

但是在每个发布的版本中,这段代码都标有@hide注解,这意味着这些方法中没有一个实际上可以使用。

在 Android 9 之前,隐藏方法至少可以在某些设备上通过 java 反射访问。这就是我们能够在 android 8 上进行测试的方式,结果很糟糕。

自操作系统版本 9 以来,这不再可能:平台 actively blocks attempts 不正确地访问 API。

此外..

除了实例化套接字的方法不可见之外,还有证据表明 API 的不成熟性还在于缺乏调整 l2cap 连接参数的方法。

走向原生?

我没有使用 NDK 的经验,但我认为可以编写 c 代码来利用隐藏方法使用的相同低级函数。除非 android 也没有阻止这种使用,否则这很可能。 此外,这种用法会与手机上蓝牙堆栈的常规用法相冲突:正常用法通常都由 Android 服务过滤。绕过此服务会导致不可预知的后果,并且不适合生产性应用。

总结一下

在 Android 8.1 上使用反射进行测试导致非常不令人满意的结果。尽管做出了努力,但无法证实自 Android 8.0 以来“面向 LE 连接的通道”的说法。

在较新的版本中,用于创建 l2cap 通道的隐藏方法正在发展,最近隐藏注释为removed。在我们拥有支持此 API 的设备之前,很难从时间上说这意味着什么。 l2cap 频道可能需要数年时间才能可靠并可供大部分 android 用户使用。

【讨论】:

您能多谈谈“非常不满意的结果”吗?它在哪些方面没有按您的预期工作? 传输速度慢,连接不可靠。希望我有时间尽快用 Q 进行测试 我刚刚在 Android Q beta 中进行了测试。似乎工作得很好。我还在 Oreo 上进行了测试,但传输速度很慢,因为它一次只允许 1 个信用点,因此每个连接事件最多 1 个数据包。但是有一个错误(在两个版本中)如果您向 Android 发送长度为 0 的数据包,read(byte[]) 报告数据包的长度为 -1 而不是 0。 也许你可以用你的新结果更新我的答案;) 我有在 Linux 上创建 L2CAP 服务器的 python 脚本,我正在使用 BluetoothDevice.createInsecureL2capChannel(int) 方法在应用程序端创建一个套接字,但得到 IOException。有人对此有任何想法吗?

以上是关于如何在 Android 中实例化 L2Cap 套接字?的主要内容,如果未能解决你的问题,请参考以下文章

蓝牙编程扫盲 L2CAP sockets

Android 10 L2CAP 连接 IOException 超时 Wii 平衡板

是否可以通过L2CAP连接iOS(11.4)和Android(10 +)

Android - 如何访问在 onResume 中的 onCreate 中实例化的 View 对象?

如何在 Android 上建立套接字连接

将密码与套接字 java 一起使用,不起作用