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

安卓开发串口接收数据

安卓串口通信基础

安卓系统本身不直接支持传统串口(如RS232)操作,通常需要通过以下方式实现:

  1. USB转串口:使用USB-to-Serial转换芯片(如FT311/CP2102)
  2. 蓝牙串口:通过BluetoothSpp或BluetoothSocket
  3. 网络转串口:通过TCP/IP协议转换

USB串口通信实现步骤

权限配置

<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />

核心依赖库

推荐使用开源库:usb-serial-for-android

安卓开发串口接收数据  第1张

implementation 'com.github.mjwalter:usb-serial-for-android:2.5.2'`

USB设备过滤

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            // 处理设备连接
        }
    }
};

串口初始化代码

步骤 代码示例 说明
获取USB设备 UsbDevice device = usbManager.getDeviceList().get(0); 获取第一个连接的设备
配置串口参数 serialPort = UsbSerialProber.getDefaultProber().probeDevice(device) 自动探测串口配置
打开串口 serialPort.open(driver) 需要配合权限请求
设置监听器 serialPort.setListener(new UsbSerialInterface.UsbSerialReadListener() {...}) 异步接收数据

完整接收示例

public class SerialService extends Service {
    private UsbSerialInterface serialPort;
    private ReadThread readThread;
    @Override
    public void onCreate() {
        UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        UsbDevice device = manager.getDeviceList().get(0); // 实际需验证设备
        serialPort = UsbSerialProber.getDefaultProber().probeDevice(device);
        // 请求USB权限(Android 6.0+)
        PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, 
            new Intent(ACTION_USB_PERMISSION), 0);
        manager.requestPermission(device, permissionIntent);
        readThread = new ReadThread(serialPort);
        readThread.start();
    }
    private static class ReadThread extends Thread {
        private final UsbSerialInterface mSerialPort;
        public ReadThread(UsbSerialInterface serialPort) {
            this.mSerialPort = serialPort;
        }
        @Override
        public void run() {
            byte[] buffer = new byte[1024];
            while (!isInterrupted()) {
                try {
                    int size = mSerialPort.syncRead(buffer, 1000); // 超时1秒
                    if (size > 0) {
                        String received = new String(buffer, 0, size);
                        // 处理接收数据
                        Log.d("Serial", "Received: " + received);
                    }
                } catch (IOException e) {
                    Log.e("Serial", "Error reading", e);
                }
            }
        }
    }
}

常见问题解决方案

问题现象 解决方案
设备无法识别 检查设备驱动是否安装,确认设备VID/PID
权限被拒绝 动态申请USB权限,处理ACTION_USB_PERMISSION广播
数据乱码 统一设置波特率(如9600)、数据位(8位)、校验位(无)
接收延迟 使用syncRead()代替read(),或开启独立线程
中文显示异常 设置UTF-8编码:new String(buffer, StandardCharsets.UTF_8)

性能优化建议

  1. 缓冲机制:使用ByteBuffer缓存数据,避免频繁创建对象
  2. 异步处理:通过Handler/RxJava切换到主线程更新UI
  3. 流量控制:设置合理的读写超时时间(如setReadBuffer(4096)
  4. 资源释放:在onDestroy()中调用serialPort.close()并中断线程

测试工具推荐

工具名称 用途 特点
virtual-here 虚拟串口调试 支持Windows/Linux
QSerialPort Qt虚拟串口 跨平台测试
CoolTerm Android串口调试 支持USB/蓝牙调试

相关问题与解答

Q1:如何判断USB设备是否支持串口通信?

  • A1:通过检查设备的USB_CLASSSUBCLASS字段:
    if (device.getDeviceClass() == UsbConstants.USB_CLASS_COMM 
      && device.getDeviceSubclass() == UsbConstants.USB_SUBCLASS_COMM_EMB) {
      // 是通信设备类
    }

    同时需要验证PROTOCOL是否为UsbConstants.USB_PROTOCOL_COMM_EMB


Q2:如何实现串口数据的十六进制显示?

  • A2:将字节数组转换为十六进制字符串:
    public String bytesToHex(byte[] bytes) {
      StringBuilder sb = new StringBuilder();
      for (byte b : bytes) {
          sb.append(String.format("%02X ", b));
      }
      return sb.toString().trim();
    }

    在接收回调中调用:String hexData = bytesToHex(buffer);

0