上一篇
安卓开发串口接收数据
- 行业动态
- 2025-04-22
- 4
安卓串口通信基础
安卓系统本身不直接支持传统串口(如RS232)操作,通常需要通过以下方式实现:
- USB转串口:使用USB-to-Serial转换芯片(如FT311/CP2102)
- 蓝牙串口:通过BluetoothSpp或BluetoothSocket
- 网络转串口:通过TCP/IP协议转换
USB串口通信实现步骤
权限配置
<uses-feature android:name="android.hardware.usb.host" /> <uses-permission android:name="android.permission.USB_PERMISSION" />
核心依赖库
推荐使用开源库:usb-serial-for-android
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) |
性能优化建议
- 缓冲机制:使用
ByteBuffer
缓存数据,避免频繁创建对象 - 异步处理:通过Handler/RxJava切换到主线程更新UI
- 流量控制:设置合理的读写超时时间(如
setReadBuffer(4096)
) - 资源释放:在
onDestroy()
中调用serialPort.close()
并中断线程
测试工具推荐
工具名称 | 用途 | 特点 |
---|---|---|
virtual-here | 虚拟串口调试 | 支持Windows/Linux |
QSerialPort | Qt虚拟串口 | 跨平台测试 |
CoolTerm | Android串口调试 | 支持USB/蓝牙调试 |
相关问题与解答
Q1:如何判断USB设备是否支持串口通信?
- A1:通过检查设备的
USB_CLASS
和SUBCLASS
字段: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);