当前位置:首页 > 行业动态 > 正文

安卓开发 串口通信

安卓串口通信基础

硬件支持与限制

  • 设备要求:安卓设备需具备物理串口(如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); // 跳过缓冲区已有数据

关键实现步骤

  1. 设备权限处理

    • 动态申请USB权限:UsbManager.requestPermission()
    • Root设备需添加android:sharedUserId="android.uid.system"
  2. 串口参数配置

    // 通过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); // 应用设置
  3. 数据收发机制

    • 发送:直接写入OutputStream
    • 接收:需创建独立线程,使用InputStream.read()阻塞读取
    • 缓冲处理:建议使用BufferedReader包装输入流

常见问题与解决方案

问题 解决方案
权限拒绝报错 使用USB授权或Root设备后重试
数据丢失/粘包 添加CRC校验,设计应用层协议包头
高波特率丢数据 启用串口硬件流控(RTS/CTS)

跨平台注意事项

平台特性 处理方案
Android 10+后台限制 使用Foreground Service保持串口连接
设备驱动差异 优先选择通用驱动(如CP210x/FTDI)
鸿蒙系统兼容 使用HAP规范重新打包驱动模块

相关问题与解答

Q1:如何保证串口数据接收的实时性?

  • A1
    1. 创建专用接收线程,使用InputStream.read(byte[])循环读取
    2. 设置接收缓冲区(建议4096字节以上)
    3. 启用硬件流控(RTS/CTS)防止数据溢出
    4. 示例代码结构:
      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 | 需要预装驱动 |
    • 实施建议
      1. 优先选择支持免驱的USB-TTL模块(如FTDI芯片)
      2. 在APK中集成驱动安装包(需处理Android 7.0+驱动签名限制)
      3. 测试阶段覆盖主流设备(如Pixel/Samsung/Huawei等
0