3步配置Android USB串口多端口:CDC/ACM双端口避坑笔记
2026/8/22 21:20:13 网站建设 项目流程

3步配置Android USB串口多端口:CDC/ACM双端口避坑笔记

【免费下载链接】usb-serial-for-androidAndroid USB host serial driver library for CDC, FTDI, Arduino and other devices.项目地址: https://gitcode.com/gh_mirrors/us/usb-serial-for-android

把一块Arduino Leonardo插到手机上,却发现设备明明有两个串口,App却只能打开第一个?usb-serial-for-android 是一个纯Java实现的 Android USB 串口驱动库,不用root、不用内核驱动,把CDC/ACM多接口设备解析成一个个独立的串口端口给你用。

你将带走什么

  • ✅ 用 UsbSerialProber 扫描全部已连接的USB设备并建立驱动列表
  • ✅ 读取双端口CDC/ACM设备的真实端口数量,分别打开每个 UsbSerialPort
  • ✅ 在 AndroidManifest 里注册 USB_DEVICE_ATTACHED 广播,插线自动拉起App
  • ✅ 自定义VID/PID不在内置探测表时,用 ProbeTable 补一条探测规则

前置条件

  • 支持USB OTG的手机/平板,加一条OTG转接线
  • Android 4.2+(3.1开始支持USB Host,但README明确说4.2起才稳定可靠)
  • 目标设备:Arduino Leonardo(ATmega32U4)、刷了双端口固件的Raspberry Pi Pico,或任何CDC/ACM多接口芯片
  • 库版本 3.11.0:
allprojects { repositories { maven { url 'https://jitpack.io' } } } dependencies { implementation 'com.github.mik3y:usb-serial-for-android:3.11.0' }

为什么是这个版本:这是README Quick Start当前给出的版本,而且3.5.0起CDC/ACM设备改按接口类型探测,双端口设备不用手写自定义探测器,多端口支持靠的就是这条改动线。

原理30秒

USB CDC/ACM设备像一栋楼:每个串口是一间房,门牌是“控制接口”(COMM类,ACM子类),数据走廊是“数据接口”(CDC_DATA类),开一扇门要一对接口各认领一个。库数房间的个数,再给你建出同样多的钥匙(UsbSerialPort)。双端口设备就是描述符里有两对接口,countPorts() 取控制/数据接口数量的较小值当端口数——固件如实报两对,你就自动拿到两个端口。

实操走查:探测并打开Android USB串口多端口

在清单文件注册USB Host广播在 AndroidManifest.xml 的目标Activity里加 USB_DEVICE_ATTACHED 的 intent-filter 和 meta-data,后者指向声明"响应哪些设备"的 device_filter.xml:

<intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />

这一段让系统在插进匹配的串口设备时自动弹出"用该应用打开"的选择框。过滤文件放在 res/xml/ 下,直接参考示例项目的 device_filter.xml,里面已收录FTDI、CP210x、PL2303、CH34x、Arduino、Pico等VID/PID;完整清单写法见 AndroidManifest.xml。

⚠️ 常见错误:插线后App不弹起。检查 device_filter.xml 是否真的在 res/xml/ 下,meta-data 的 name 是否一字不差写对——写错一个字符就静默失效,不报错。

探测设备并打开端口用 UsbSerialProber 拿到驱动列表,再用 getPorts() 取端口列表,双端口设备的列表就是两个元素:

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); List<UsbSerialDriver> drivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); UsbSerialDriver driver = drivers.get(0); UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); UsbSerialPort port = driver.getPorts().get(1); // 打开第二个端口 port.open(connection); port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

findAllDrivers 只查设备树、不需要权限;openDevice 才是第一个要权限的调用,首次需要弹 requestPermission 等用户授权,setParameters 必须在 open 之后调,它不会替你默认设置。

⚠️ openDevice 返回 null 通常不是代码问题,而是权限弹窗被点掉或App不在前台。要用 BroadcastReceiver 接权限结果并重试,示例项目 MainActivity.java 有这套完整流程可以抄。

核对端口计数逻辑插上双端口设备、App里却只有一个端口时,翻一下 CdcAcmSerialDriver.java:构造器调用 countPorts() 分别统计"COMM类ACM控制接口"和"CDC_DATA数据接口"的数量,取较小值当端口数。也就是说固件必须上报两对完整接口;只报一对(某些阉割版CDC固件)时,库会退回单端口逻辑,日志里打一句 "device might be castrated ACM device"。仓库 test/arduino_leonardo_bridge_multi_cdc/ 里有一份现成的双接口Leonardo固件,USBDesc.h 是其中的USB描述符配置,改完刷进去就能复现双端口。

跑通数据端口打开后直接读写,或把读交给独立线程回调:

byte[] response = new byte[64]; int len = port.read(response, 1000); port.write("ping".getBytes(), 1000);

两个参数都是毫秒超时。完整终端界面(含 SerialInputOutputManager 异步读、Xon/Xoff 流控)在示例项目 TerminalFragment.java。注意关固定端口再重开时务必先 close(),否则控制接口的占用不释放,下次 open 直接抛 "Could not claim"。

踩坑记录

插上设备但日志里没有端口号

现象:findAllDrivers 返回空。原因:设备接口类型和VID/PID都不在探测表里。解法:先看logcat里接口类,CDC/ACM按3.5.0起应能命中;没命中就补一条自定义探测,见下文扩展。

openDevice 返回 null

现象:设备已插上,openDevice 是 null。原因:权限弹窗被点掉或App不在前台。解法:注册 BroadcastReceiver 接权限结果再重试,参考示例 MainActivity 的写法。

双端口CDC/ACM设备只有一个端口

现象:getPorts().size() == 1。原因:固件只上报了一对接口。解法:检查描述符里的接口对,刷仓库 test/arduino_leonardo_bridge_multi_cdc/ 的双端口固件再验证。

扩展与调优

自定义探测:遇到自定义VID/PID的新芯片,往 ProbeTable 加一行再交给 UsbSerialProber 即可,示例在 CustomProber.java,内置VID/PID表在 ProbeTable.java。想深入可以看README的 Probing 一节。

异步I/O:SerialInputOutputManager 在独立线程里读数据、用回调推给UI,主线程不会卡在 read 超时里,多端口各自挂一个实例即可。想深入可以看 SerialInputOutputManager.java。

控制线:CdcAcmSerialPort 有后台线程读 DTR/RTS/CD 状态,getCD() 能判断对端是否在线,逻辑都在前面提到的 CdcAcmSerialDriver.java 里,做多设备在线监控时用得上。

速查清单

项目内容
依赖com.github.mik3y:usb-serial-for-android:3.11.0(jitpack仓库)
系统Android 4.2+,USB OTG设备
清单注册USB_DEVICE_ATTACHED intent-filter + meta-data
过滤文件res/xml/device_filter.xml(可抄示例项目)
多端口计数规则min(COMM/ACM控制接口数, CDC_DATA数据接口数)
打开顺序requestPermission → openDevice → port.open → setParameters → read/write
关闭先 port.close() 再重开,否则接口占用不释放

延伸阅读

  • README.md 官方文档,含完整 Quick Start 和兼容芯片清单
  • CdcAcmSerialDriverTest.java 单元测试,看多端口计数是怎么被覆盖的
  • test/pi_pico/ 双端口Pico固件,刷一个现成的双端口CDC设备出来就能反复验证

跑通之后记得去仓库Issues里翻翻别人新踩的坑,多端口这块的描述符问题还不少。

【免费下载链接】usb-serial-for-androidAndroid USB host serial driver library for CDC, FTDI, Arduino and other devices.项目地址: https://gitcode.com/gh_mirrors/us/usb-serial-for-android

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询