在Android实现USB链接有什么做用?USB链接有什么限制?USB链接实现的难度?android
在Android上实现USB链接的用处在于能够在搭载Android系统的手机或者开发板上控制设备。例如:Android控制USB摄像头、Android控制USB打印机、Android控制身份证读卡器......理论上只要支持USB链接的设备均可以用Android实现控制。固然这里的控制分为两种状况:git
USB免驱设备。(驱动部分已在Android底层或Linux层实现)github
USB指定驱动设备。(硬件厂家驱动、通用通信协议 服务器
对于USB设备链接来讲就像客户端链接服务器,在网络链接中须要知道服务器的ip地址才能找到对应的服务器,同理在USB链接中也是须要知道对应USB设备的vendorId(设备厂商Id)和productId(设备产品Id)。在我开发过的USB的设备中发现这两个Id在同一厂商生产的相同系列的不一样产品中,他们可能会重复。和网络链接不一样的是,若是不知道这两个Id,也是能够链接设备,只是不知道链接的哪个,这里的id主要是用于链接和过滤设备用的网络
其实USB设备的链接比较简单,比较如今USB设备已经至关普及、不管是经过Android系统仍是经过Linux系统你均可以很好的实现。可能对于平时没有在Android接触过USB通讯的感受难而已,等你看完本文后你会以为真的很简单。并且这个是不须要root权限的,看完本文后你就能够用你Android手机实现控制一个外接摄像头,想一想是否是很激动。ui
若是你是在Android手机这样不支持USB链接的设备上实现,能够经过在type-c上用OTG扩展出USB母口(淘宝5元包邮),若是你实在Android开发板上实现USB链接,直连就能够,通常开发板都支持USB口。若是你想控制更多的USB设备能够经过USB扩展器实现。code
首先在AndroidManifest.xml中申明USB权限xml
<!-- 声明使用usb --> <uses-feature android:name="android.hardware.usb.host" android:required="true" />
而后在你操做的Activity或service中添加meta-data对象
<!-- android设备的信息过滤 --> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/usb_xml" />
这里的usb_xml文件为res文件夹下的xml文件夹中的设备过滤文件接口
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="10473" product-id="649"/> <usb-device vendor-id="1336" product-id="0" /> <usb-device vendor-id="1061" product-id="33113" /> <usb-device vendor-id="17224" product-id="33113" /> </resources>
这里的每个usb-device对应一个usb设备。
链接USB设备前,首先要经过vendorId和productId过滤出咱们须要的设备操做对象UsbDevice
/** * 找到自定设备 */ public void findUSB(int VENDORID, int PRODUCTID) { //1)建立usbManager 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.i(TAG, "vendorID--" + device.getVendorId() + "ProductId--" + device.getProductId()); if (device.getVendorId() == VENDORID && device.getProductId() == PRODUCTID) { usbDevice = device; // 获取USBDevice } } }
根据USBDevice找到指定的设备接口UsbInterface,一个设备上面通常只有一个接口,有两个端点,分别接受和发送数据
UsbInterface usbInterface = null; for (int i = 0; i < usbDevice.getInterfaceCount(); i++) { //一个设备上面通常只有一个接口,有两个端点,分别接受和发送数据 usbInterface = usbDevice.getInterface(i); break; }
USB通讯通道即和USB设备间接收和发送的经过,经过获取通道中对应的断点发送或接收数据实现控制。
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; } }
在打开USB设备的时候是须要申请USB链接权限的,并且申请权限的次数是根据链接的设备来肯定。也就是说须要给每一个usb设备单独受权(这个也好理解,只是不少时候系统USB权限弹窗都同样,多个设备时体验很差,若是要修改我认为只能从系统层面解决)。
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链接就已经完成了。整个链接就像Socket似的,你若是不主动释放,正常状况下他不会断开。
if (conn.claimInterface(usbInterface, true)) { if (conn != null)// 到此你的android设备已经连上zigbee设备 Log.i(TAG, "open设备成功!"); final String mySerial = conn.getSerial(); Log.i(TAG, "设备serial number:" + mySerial); } else { Log.i(TAG, "没法打开链接通道。"); conn.close(); }
当USB链接完成后就能够进行数据发送了,这里发送的一般都是字节数据,设备根据他本身的方式解析数据作出对应的响应。
public void sendData(byte[] buffer) { if (conn == null || epBulkOut == null) return; if (conn.bulkTransfer(epBulkOut, buffer, buffer.length, 0) >= 0) { //0 或者正数表示成功 Log.i(TAG, "发送成功"); } else { Log.i(TAG, "发送失败的"); } }
当你不用的时候必定要记得关闭链接释放资源
conn.close();
对于USB链接其实就经过简单的几步就能实现USB设备与Android系统的通讯,是否是很简单。我把Android系统USB通信、Android系统串口通讯、Android系统Pos打印、Android系统gpio控制、Android上USB链接Camera、Android系统上实现双屏异显等示例代码都放到github上(CSDN如今下载须要积分,暂时就不上传了),代码如今尚未整理,若有什么不合理的地方,但愿大佬们指正 QQ 962851730。后续将陆续推出以上系列播客。