简介

在Android实现USB连接有什么作用?USB连接有什么限制?USB连接实现的难度?

1.Android实现USB连接有什么作用?

在Android上实现USB连接的用处在于可以在搭载Android系统的手机或者开发板上控制设备。例如:Android控制USB摄像头、Android控制USB打印机、Android控制身份证读卡器......理论上只要支持USB连接的设备都可以用Android实现控制。当然这里的控制分为两种情况:

  • USB免驱设备。(驱动部分已在Android底层或Linux层实现)

  • USB指定驱动设备。(硬件厂家驱动、通用通讯协议 

2.USB连接有什么限制?

对于USB设备连接来说就像客户端连接服务器,在网络连接中需要知道服务器的ip地址才能找到对应的服务器,同理在USB连接中也是需要知道对应USB设备的vendorId(设备厂商Id)和productId(设备产品Id)。在我开发过的USB的设备中发现这两个Id在同一厂商生产的相同系列的不同产品中,他们可能会重复。和网络连接不同的是,如果不知道这两个Id,也是可以连接设备,只是不知道连接的哪一个,这里的id主要是用于连接和过滤设备用的

3.USB连接实现的难度?

其实USB设备的连接比较简单,比较现在USB设备已经相当普及、不论是通过Android系统还是通过Linux系统你都可以很好的实现。可能对于平时没有在Android接触过USB通信的感觉难而已,等你看完本文后你会觉得真的很简单。而且这个是不需要root权限的,看完本文后你就可以用你Android手机实现控制一个外接摄像头,想想是不是很激动。

实现步骤

1.物理连接

如果你是在Android手机这样不支持USB连接的设备上实现,可以通过在type-c上用OTG扩展出USB母口(淘宝5元包邮),如果你实在Android开发板上实现USB连接,直连就可以,一般开发板都支持USB口。如果你想控制更多的USB设备可以通过USB扩展器实现。

2.权限配置

首先在AndroidManifest.xml中申明USB权限

     

然后在你操作的Activity或service中添加meta-data

             

这里的usb_xml文件为res文件夹下的xml文件夹中的设备过滤文件

<?xml version="1.0" encoding="utf-8"?>                

这里的每一个usb-device对应一个usb设备。

3.找到指定USB设备

连接USB设备前,首先要通过vendorId和productId过滤出我们需要的设备操作对象UsbDevice

/**     * 找到自定设备     */    public void findUSB(int VENDORID, int PRODUCTID) {        //1)创建usbManager        usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);        //2)获取到所有设备 选择出满足的设备        HashMap deviceList = usbManager.getDeviceList();        Iterator 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            }        }    }

4.查找设备接口

根据USBDevice找到指定的设备接口UsbInterface,一个设备上面一般只有一个接口,有两个端点,分别接受和发送数据
 

UsbInterface usbInterface = null;        for (int i = 0; i < usbDevice.getInterfaceCount(); i++) {            //一个设备上面一般只有一个接口,有两个端点,分别接受和发送数据            usbInterface = usbDevice.getInterface(i);            break;        }

5.获取usb设备的通信通道

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;            }        }

6.打开USB设备连接

在打开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, "没有权限");            }        }

7.请求接口

到此整个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();        }

8.发送数据

当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, "发送失败的");        }    }

9.关闭USB连接

当你不用的时候一定要记得关闭连接释放资源

conn.close();

结语

对于USB连接其实就通过简单的几步就能实现USB设备与Android系统的通信,是不是很简单。我把Android系统USB通讯、Android系统串口通信、Android系统Pos打印、Android系统gpio控制、Android上USB连接Camera、Android系统上实现双屏异显等示例代码都放到github上(CSDN现在下载需要积分,暂时就不上传了),代码现在还没有整理,如有什么不合理的地方,希望大佬们指正 QQ 962851730。后续将陆续推出以上系列播客。

 

更多相关文章

  1. Android 的系统架构
  2. Android编译系统(四):Android 编译系统框架分析及main.mk分析
  3. [Android]发布Sqlite数据库
  4. Android Wear带你理解跨设备的Android 技术体系
  5. android sd卡读取数据库
  6. Android架构组件- Room数据库的使用
  7. Android系统中TextView实现滚动效果
  8. 推荐几本可以深入了解android系统应用开发的书籍
  9. Android 5.1 open data flow 数据开启流程

随机推荐

  1. Android教程:LayerDrawable层叠样式layer-
  2. Binder机制1---Binder原理介绍
  3. Android(安卓)定时任务过程详解
  4. Android Studio FFMPEG 入门
  5. android 开发技巧(8)--格式化 TextView
  6. 查看 apk 的信息
  7. Android线程间通信的Message机制
  8. Gradle在Android(安卓)Studio 的应用
  9. Android 服务的五大级别
  10. 2011.09.23——— android sample之Notep