上一篇
安卓开发 串口通信
- 行业动态
- 2025-04-22
- 4
安卓串口通信基础
硬件支持与限制
- 设备要求:安卓设备需具备物理串口(如OTG接口连接的USB-TTL模块)或通过扩展板支持串口通信。
- 系统权限:安卓系统默认不开放串口设备访问权限,需通过Root或特定驱动绕过限制。
核心概念
参数 | 说明 | 常见值 |
---|---|---|
波特率 | 通信速率(bps) | 9600/115200 |
数据位 | 每个字符的位数 | 8位 |
停止位 | 字符结束标志 | 1位 |
校验位 | 错误检测方式 | 无校验(N) |
实现方案对比
原生API开发(需Root权限)
// 示例:通过FileInputStream/OutputStream操作串口 File device = new File("/dev/ttyS1"); // 替换为实际设备节点 int baudRate = 9600; // 配置串口参数(需JNI调用termios库) // 省略具体实现... FileInputStream fis = new FileInputStream(device); FileOutputStreamfos = new FileOutputStream(device); // 发送数据 fos.write("Hello".getBytes()); // 接收数据(需开线程循环读取) byte[] buffer = new byte[1024]; int len = fis.read(buffer); String data = new String(buffer, 0, len);
USB-Serial For Android方案
组件 | 说明 |
---|---|
USB驱动 | Prolific/FTDI等芯片驱动 |
权限声明 | android:permission="android.permission.USB_PERMISSION" |
设备过滤 | 通过USB_DEVICE_CLASS匹配串口设备 |
<!-AndroidManifest.xml --> <uses-feature android:name="android.hardware.usb.host" /> <meta-data android:name="android.hardware.usb.action" android:resource="@xml/device_filter" />
第三方库方案(推荐)
库名称 | 特点 |
---|---|
SerialPortLib | 轻量级,支持USB/蓝牙串口 |
UsbSerial | 基于Google USB库,支持多厂商设备 |
// 使用SerialPortLib示例 SerialPort mSerialPort = new SerialPort(new File(devicePath), baudRate, flags); // 发送数据 mSerialPort.getOutputStream().write("Test".getBytes()); // 接收数据(需设置监听器) mSerialPort.getInputStream().skip(availableBytes); // 跳过缓冲区已有数据
关键实现步骤
设备权限处理
- 动态申请USB权限:
UsbManager.requestPermission()
- Root设备需添加
android:sharedUserId="android.uid.system"
- 动态申请USB权限:
串口参数配置
// 通过JNI调用termios设置(C代码示例) struct termios options; tcgetattr(fd, &options); // 获取当前设置 cfsetispeed(&options, B9600); // 输入波特率 cfsetospeed(&options, B9600); // 输出波特率 options.c_cflag &= ~PARENB; // 无校验 options.c_cflag |= CS8; // 8数据位 tcsetattr(fd, TCSANOW, &options); // 应用设置
数据收发机制
- 发送:直接写入OutputStream
- 接收:需创建独立线程,使用
InputStream.read()
阻塞读取 - 缓冲处理:建议使用
BufferedReader
包装输入流
常见问题与解决方案
问题 | 解决方案 |
---|---|
权限拒绝报错 | 使用USB授权或Root设备后重试 |
数据丢失/粘包 | 添加CRC校验,设计应用层协议包头 |
高波特率丢数据 | 启用串口硬件流控(RTS/CTS) |
跨平台注意事项
平台特性 | 处理方案 |
---|---|
Android 10+后台限制 | 使用Foreground Service保持串口连接 |
设备驱动差异 | 优先选择通用驱动(如CP210x/FTDI) |
鸿蒙系统兼容 | 使用HAP规范重新打包驱动模块 |
相关问题与解答
Q1:如何保证串口数据接收的实时性?
- A1:
- 创建专用接收线程,使用
InputStream.read(byte[])
循环读取 - 设置接收缓冲区(建议4096字节以上)
- 启用硬件流控(RTS/CTS)防止数据溢出
- 示例代码结构:
new Thread(() -> { byte[] buffer = new byte[4096]; while (isRunning) { int len = inputStream.read(buffer); if (len > 0) { // 处理接收到的数据 } } }).start();
- 创建专用接收线程,使用
Q2:如何处理不同安卓设备的驱动兼容性问题?
- A2:
- 方案对比表:
| 方案 | 优点 | 缺点 |
|———————|——————————-|——————————-|
| USB-Serial For Android | 官方支持,稳定性好 | 需修改系统镜像,仅支持特定芯片 |
| 通用CH340驱动 | 广泛兼容,免修改系统 | 依赖Root权限 |
| FTDI/Prolific驱动 | 即插即用,无需Root | 需要预装驱动 | - 实施建议:
- 优先选择支持免驱的USB-TTL模块(如FTDI芯片)
- 在APK中集成驱动安装包(需处理Android 7.0+驱动签名限制)
- 测试阶段覆盖主流设备(如Pixel/Samsung/Huawei等
- 方案对比表: