现在好多设备都有USB接口,在Android系统的手机或者开发板上可以实现通过USB来控制设备。一般手机上没有USB接口,需要使用OTG功能的转接线扩展出USB母口;一般Android开发板上带有USB口就可以直接使用了。
USB连接中需要知道对应USB设备的vendorId(设备厂商Id)和productId(设备产品Id),这两个id主要是用于连接和过滤设备。那么下面我们就先来看下拿到设备怎样找设备的vendorId和productId:
(1)先将设备通过USB口连接到电脑上;
(2)我的电脑->管理->设备管理器->找到链接的usb设备->右键属性->详细信息->硬件ID->其中的VID就是厂商id、PID是产品id。如下图所示:
这个ID是16进制的,需要转换成10进制的在 xml---device_filter.xml文件里配置。
在res目录下新建文件夹,名字是xml,然后再xml文件夹里新建device_filter.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!--设备过滤文件-->
<!-- devices vendor-id= 0x1F3A product-id=0x1007-->
<usb-device vendor-id="7994" product-id="4103"/>
</resources>
这里的每一个usb-device对应一个usb设备;如果应用需要对多个设备使用,这里可以添加多个usb-device对应的usb设备的vendor-id和product-id;如果应用可以对同一个厂商的所有设备使用,这里可以只写vendor-id(个人是这么理解的)。
前面的准备工作做好了就可以进行下面的开发了:
(1)在AndroidManifest.xml中申明USB权限:
<!-- 声明使用usb -->
<uses-feature
android:name="android.hardware.usb.host"
android:required="true" />
(2)在AndroidManifest.xml中对应Activity中添加下面内容:
<!--获取USB操作的通知-->
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
</intent-filter>
<!-- android设备的信息过滤 -->
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb_xml"/>
通过设备的vendorId(设备厂商Id)和productId(设备产品Id)找到设备
/**
* 找到自定设备
*/
public UsbDevice getUsbDevice(int vendorId, int productId) {
//1)创建usbManager
if (usbManager == null)
usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
//2)获取到所有设备 选择出满足的设备
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
Log.e(TAG, "vendorID--" + device.getVendorId() + "ProductId--" + device.getProductId());
if (device.getVendorId() == vendorId && device.getProductId() == productId) {
return device; // 获取USBDevice
}
}
statue = USBContent.usb_find_this_fail;
return null;
}
查找所有连接的USB设备,与上面的通过id查找设备 两者根据实际情况来选用。
/**
* 查找本机所有的USB设备
*/
public List<UsbDevice> getUsbDevices() {
//1)创建usbManager
if (usbManager == null)
usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
//2)获取到所有设备 选择出满足的设备
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
//创建返回数据
List<UsbDevice> lists = new ArrayList<>();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
Log.e(TAG, "vendorID--" + device.getVendorId() + "ProductId--" + device.getProductId());
lists.add(device);
}
return lists;
}
连接USB设备
/**
* 根据指定的vendorId和productId连接USB设备
*
* @param vendorId 产商id
* @param productId 产品id
*/
public int connection(int vendorId, int productId) {
usbDevice = getUsbDevice(vendorId, productId);
//3)查找设备接口
if (usbDevice == null) {
Log.e(TAG, "未找到目标设备,请确保供应商ID" + vendorId + "和产品ID" + productId + "是否配置正确");
return statue;
}
UsbInterface usbInterface = null;
for (int i = 0; i < usbDevice.getInterfaceCount(); i++) {
//一个设备上面一般只有一个接口,有两个端点,分别接受和发送数据
usbInterface = usbDevice.getInterface(i);
Log.e("USBHelper","usbInterface.getEndpointCount()="+usbInterface.getEndpointCount());
break;
}
//4)获取usb设备的通信通道endpoint
for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
UsbEndpoint ep = usbInterface.getEndpoint(i);
switch (ep.getType()) {
case UsbConstants.USB_ENDPOINT_XFER_BULK://USB端口传输
if (UsbConstants.USB_DIR_OUT == ep.getDirection()) {//输出
epBulkOut = ep;
Log.e(TAG, "获取发送数据的端点");
} else {
epBulkIn = ep;
Log.e(TAG, "获取接收数据的端点");
}
break;
case UsbConstants.USB_ENDPOINT_XFER_CONTROL://控制端点
epControl = ep;
Log.e(TAG, "find the ControlEndPoint:" + "index:" + i + "," + epControl.getEndpointNumber());
break;
case UsbConstants.USB_ENDPOINT_XFER_INT://中断端点
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {//输出
epIntEndpointOut = ep;
Log.e(TAG, "find the InterruptEndpointOut:" + "index:" + i + "," + epIntEndpointOut.getEndpointNumber());
}
if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
epIntEndpointIn = ep;
Log.e(TAG, "find the InterruptEndpointIn:" + "index:" + i + "," + epIntEndpointIn.getEndpointNumber());
}
break;
default:
break;
}
}
//5)打开conn连接通道
if (usbManager.hasPermission(usbDevice)) {
//有权限,那么打开
conn = usbManager.openDevice(usbDevice);
} else {//没有权限
usbManager.requestPermission(usbDevice, intent);// 先去获取权限
if (usbManager.hasPermission(usbDevice)) { // 权限获取成功
conn = usbManager.openDevice(usbDevice);
} else {
Log.e(TAG, "USB授权失败");
statue = USBContent.usb_permission_fail;
}
}
if (null == conn) {
Log.e(TAG, "不能连接到设备");
statue = USBContent.usb_open_fail;
return statue;
}
//打开设备
if (conn.claimInterface(usbInterface, true)) {
if (conn != null)// 到此你的android设备已经连上设备
Log.e(TAG, "open设备成功!");
final String mySerial = conn.getSerial();
Log.e(TAG, "设备serial number:" + mySerial);
statue = USBContent.usb_ok;
} else {
Log.e(TAG, "无法打开连接通道。");
statue = USBContent.usb_passway_fail;
conn.close();
}
return statue;
}
发送数据
/**
* 通过USB发送数据
*/
public void sendData(byte[] buffer) {
if (conn == null || epBulkOut == null) return;
int res = conn.bulkTransfer(epBulkOut, buffer, buffer.length, 1000);
Log.e(TAG, "res="+res);
if (res >= 0) {
//0 或者正数表示成功
Log.e(TAG, "发送成功");
statue = USBContent.usb_permission_ok;
} else {
Log.e(TAG, "发送失败的");
statue = USBContent.usb_permission_fail;
}
}
使用完关闭USB连接
/**
* 关闭USB连接
*/
public void close() {
if (conn != null) { //关闭USB设备
conn.close();
conn = null;
}
if (mContext != null && broadcastReceiver != null) {
mContext.unregisterReceiver(broadcastReceiver);
}
}
到这里USB的连接、通过USB向硬件设备发送数据就完成了,在此做下记录,方便以后参考使用。大家如果看到了此文章,如果发现哪里有问题欢迎指正。(本人也是刚刚接触USB通信,对USB通信了解有限,上面这个是用到了亲自试验的记录一下)
感谢参考文章:https://blog.csdn.net/u013057253/article/details/82725585
还有一篇USB协议基本知识文章个人感觉写的也不错,对刚接触USB的会有帮助,附上个链接https://blog.csdn.net/u010142953/article/details/82627591