前言
通过usb可以和外接设备进行数据交互,比如开发板,外设,单片机等。两台android设备如何连接?通过usb转232线,实现消息通讯。
实现方式
相关类:
UsbManager
UsbDevice
getSerialNumber() 设备唯一序列号
getDeviceId() 此设备的ID号
getDeviceName() 设备的名称
getVendorId() 生产商ID
getProductId() 产品ID
- 寻找已连接的设备
ArrayBlockingQueue<PendingUsbPermission> queuedPermissions = new ArrayBlockingQueue<>(100);
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE)
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
//筛选目标设备
Timber.d("USBDevice.HashMap (vid:pid) (%X:%X class:%X:%X name:%s",
device.getVendorId(), device.getProductId(),
device.getDeviceClass(), device.getDeviceSubclass(),
// 为找到的设备请求使用权限
queuedPermissions.add(createUsbPermission(context, new UsbDeviceStatus(device)));
}
launchPermission();
- 权限请求
/**
* 统一请求权限
*/
private void launchPermission() {
try {
processingPermission = true;
currentPendingPermission = queuedPermissions.take();
usbManager.requestPermission(currentPendingPermission.usbDeviceStatus.usbDevice,
currentPendingPermission.pendingIntent);
} catch (InterruptedException e) {
e.printStackTrace();
processingPermission = false;
}
}
/**
* 构建请求意图
* @param context
* @param usbDeviceStatus
* @return
*/
private PendingUsbPermission createUsbPermission(Context context, UsbDeviceStatus usbDeviceStatus) {
PendingIntent mPendingIntent = PendingIntent.getBroadcast(context, 0,
new Intent(ACTION_USB_PERMISSION), 0);
PendingUsbPermission pendingUsbPermission = new PendingUsbPermission();
pendingUsbPermission.pendingIntent = mPendingIntent;
pendingUsbPermission.usbDeviceStatus = usbDeviceStatus;
return pendingUsbPermission;
}
private class UsbDeviceStatus {
public UsbDevice usbDevice;
public UsbDeviceConnection usbDeviceConnection;
public boolean open;
public UsbDeviceStatus(UsbDevice usbDevice) {
this.usbDevice = usbDevice;
}
@Override
public boolean equals(Object obj) {
UsbDeviceStatus usbDeviceStatus = (UsbDeviceStatus) obj;
return usbDeviceStatus.usbDevice.getDeviceId() == usbDevice.getDeviceId();
}
}
- 权限获取后处理
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent arg1) {
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
Timber.e("device ACTION_USB_PERMISSION");
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
// User accepted our USB connection. Try to open the device as a serial port
if (granted) {
//
initSerialPort(currentPendingPermission.usbDeviceStatus.usbDevice);
if (queuedPermissions.size() > 0) {
launchPermission();
} else {
processingPermission = false;
//通信线程,获取消息,发送消息
// callback 自定义消息处理
new ConnectionThread(1, port, callback).start();
}
}
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
//todo
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
//todo
}
}
};
- 连接线程
private class ConnectionThread extends Thread {
UsbSerialDevice serialPort;
UsbSerialInterface.UsbReadCallback mCallback;
public ConnectionThread(int type, UsbSerialDevice inSerial, UsbSerialInterface.UsbReadCallback inCallback) {
mType = type;
serialPort = inSerial;
mCallback = inCallback;
}
@Override
public void run() {
if (serialPort != null) {
if (serialPort.open()) {
// 波特率,起始位,终止位,数据位
serialPort.setBaudRate(BAUD_RATE);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
/**
* Current flow control Options:
* UsbSerialInterface.FLOW_CONTROL_OFF
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
*/
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
serialPort.getCTS(ctsCallback); //Clear To Send 清除发送
serialPort.getDSR(dsrCallback); //Data Set Ready 数据准备好
//
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
// to be uploaded or not
//Thread.sleep(2000); // sleep some. YMMV with different chips.
} else {
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
// todo 自处理
}
} else {
// No driver for given device, even generic CDC driver could not be loaded 自处理
}
}
}
总结:
- 依赖库可作为jar包引入
- usb的通信不限于232,只是举例使用,可用于任意usb通信
- 本文列举所有关键类的使用