Android连接多个usb,Android实现USB连接

前言

在Android开发过程中,我们有时会涉及到USB连接的问题,这里为了方便USB连接的使用,我将相关知识封装成了一个工具类—USBHelper,下面就来介绍下它的使用吧。

今天涉及的内容有:

USB 权限相关设置

USB 设备接口确定

USB 连接流程讲解

USBHelper在 MainActivity 中的使用

项目结构图

USBHelper 源码

一. USB 权限相关设置

1.1 Android设备上打开 OTG 开关

USB连接涉及到OTG技术,需要我们在带有USB接口的Android设备上打开相关设置。在Android设备上操作如下:

设置 -----> 更多设置 -----> OTG Host //将OTG Host 开关打开

1.2 在 androidmanifast.xml 中添加 usb 权限

在 Androidmanifast.xml 中添加如下权限:

android:name="android.hardware.usb.host"

android:required="true" />

然后在 Androidmanifast.xml 中给要进行USB连接的Activity下添加usb列表文件。假设我们要在MainActivity中进行USB连接,则在 Androidmanifast.xml 中的MainActivity注册下添加以下代码:

android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"

android:resource="@xml/usb" />

主要是在Usb连接相关的Activity注册下添加下面的代码:

android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"

android:resource="@xml/usb" />

这里我们需要在res/下新建xml文件夹,然后在xml文件夹下新建usb.xml文件。即usb.xml路径为:res/xml/usb.xml。usb.xml文件中主要放置的是每个USB接口相关信息(因为一个Android设备可能有多个USB接口),usb.xml文件内容大致如下:

usb.xml里面基本是放的一个Android设备中所有USB接口的信息了。以上代码中,一个即代表一个USB接口了。通常一个USB接口中有很多信息,包括vendor-id,product-id,DeviceID等信息。这里需要注意的是,同一个usb接口热插拔一次,DeviceID是会变化的,标记一个USB接口的唯一性,我们通常用vendor-id和product-id。

二. USB 设备接口确定

上面我们已经讲过了一个Android设备可能有很多USB接口,而区分一个USB接口的唯一性我们是用vendor-id和product-id。

首先,我们需要获取一个Android设备上所有USB接口信息列表,这里我们可以用USBHelper中的以下方法获得:

/**

* 获取设备所有USB接口信息

*

* @param context

* @return 设备无USB接口时,返回 null

*/

public String getUSBListInfo(Context context)

所有USB接口信息列表我们已经获得了,这样我们就可以把每个USB接口相关信息按上面讲的格式填入res/xml/usb.xml文件中了。那么怎么确定某个USB接口的vendor-id呢?

这里可以使用USBHelper中的以下方法:

//监听热插拔,找特定usb接口

mUSBHelper.registerUsb(new USBHelper.OnHotplugListener() {

@Override

public void find(UsbDevice device) {

int vendorId=device.getVendorId();

int productId=device.getProductId();

ToastUtil.shortShow("vendorId="+vendorId+" productId="+productId);

}

@Override

public void permission(boolean status) {

if(status){

LogUtil.i("======USB授权成功======");

}else{

LogUtil.i("======USB授权失败======");

}

}

});

这里其实是监听了USB插拔动作的广播,当我们在给USB接上和拔出的时候,以上方法中的find(UsbDevice device)中便可获得此接口的device,然后我们就可以通过该device获得该USB接口的vendorId和productId了。

三. USB 连接流程讲解

上面已经讲解了如何配置USB相关设置及找到具体USB接口连接时需要的信息。接下来讲讲USB连接的流程。

USB连接的流程分以下几步:

找到特定设备UsbDevice(需要根据具体的vendorId和productId)

检测USB权限

找接口对象UsbInterface

找usb通信通道

打开USB设备

usb建立连接

USB数据传输

USB通讯结束后关闭usb

四. USBHelper在 MainActivity 中的使用

下面给出USBHelper在 MainActivity 中使用代码:

public class MainActivity extends AppCompatActivity{

private TextView mTv;

private Button mBtn;

private USBHelper mUSBHelper;

private UsbDeviceConnection mUsbDeviceConnection;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

LogUtil.setDebug(true);

initView();

initData();

setListener();

}

private void initView() {

mTv = findViewById(R.id.tv);

mBtn = findViewById(R.id.btn);

}

private void initData() {

mUSBHelper=new USBHelper(MainActivity.this);

}

private void setListener() {

//监听热插拔,找特定usb接口

mUSBHelper.registerUsb(new USBHelper.OnHotplugListener() {

@Override

public void find(UsbDevice device) {

int vendorId=device.getVendorId();

int productId=device.getProductId();

ToastUtil.shortShow("vendorId="+vendorId+" productId="+productId);

}

@Override

public void permission(boolean status) {

if(status){

LogUtil.i("======USB授权成功======");

}else{

LogUtil.i("======USB授权失败======");

}

}

});

mBtn.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//遍历usb信息

String info=mUSBHelper.getUSBListInfo(MainActivity.this);

LogUtil.i("info="+info);

//建立连接

Mapmap=mUSBHelper.connectProcess(6495,1);

int tag=mUSBHelper.getMapTag(map);

switch (tag) {

case USBHelper.DEVICE_NOT_FOUNT://无usb设备

LogUtil.i("无usb设备");

break;

case USBHelper.NO_PERMISSION://无usb权限

LogUtil.i("无usb权限");

// //申请权限

// mUSBHelper.requestUsbPermission();

break;

case USBHelper.NO_INTERFACE://查找设备接口失败

LogUtil.i("查找设备接口失败");

break;

case USBHelper.NO_BULKOUT_CHANNEL://查找输出端点失败

LogUtil.i("查找输出端点失败");

break;

case USBHelper.NO_BULKIN_CHANNEL://查找读入端点失败

LogUtil.i("查找读入端点失败");

break;

case USBHelper.NO_CONTROL_CHANNEL://查找控制端点失败

LogUtil.i("查找控制端点失败");

break;

case USBHelper.NO_POINTOUT_CHANNEL://查找中断输出端点失败

LogUtil.i("查找中断输出端点失败");

break;

case USBHelper.NO_POINTIN_CHANNEL://查找中断读入端点失败

LogUtil.i("查找中断读入端点失败");

break;

case USBHelper.NO_OPEN://USB设备打开失败

LogUtil.i("USB设备打开失败");

break;

case USBHelper.CONNECT_FAILED://USB建立连接失败

LogUtil.i("USB建立连接失败");

break;

case USBHelper.CONNECT_SUCCESS://USB建立连接成功

LogUtil.i("USB建立连接成功");

mUsbDeviceConnection= (UsbDeviceConnection) mUSBHelper.getMapValue(map);

break;

default:

break;

}

//发送数据

new Thread(new Runnable() {

@Override

public void run() {

//发送数据

String message = "我是大神";

boolean flag=mUSBHelper.writeMessage(message,mUsbDeviceConnection,null);

if(flag){

LogUtil.i("发送成功");

}else{

LogUtil.i("发送失败");

}

}

}).start();

}

});

}

@Override

protected void onDestroy() {

//关闭USB

mUSBHelper.close(mUsbDeviceConnection);

super.onDestroy();

}

}

这里需要注意的是, String info=mUSBHelper.getUSBListInfo(MainActivity.this);只是用于罗列一个Android设备上Usb接口信息列表,然后在建立连接:

Mapmap=mUSBHelper.connectProcess(6495,1);

中的参数6495,1可以通过插拔USB接口,然后在mUSBHelper.registerUsb(new USBHelper.OnHotplugListener())方法中的find(UsbDevice device)中找到vendorId和productId。

然后USB连接流程已经封装到了:

/**连接sub流程**/

public Map connectProcess(int vendorId,int productId)

方法中,大家只要调用此方法就好,若USB无权限,大家可以在case USBHelper.NO_PERMISSION中进行Usb权限申请,就像下面这样:

case USBHelper.NO_PERMISSION://无usb权限

LogUtil.i("无usb权限");

//申请权限

mUSBHelper.requestUsbPermission();

break;

然后申请结果可以在mUSBHelper.registerUsb(new USBHelper.OnHotplugListener())方法中的permission(boolean status)中看到。

usb建立成功后,可以在case USBHelper.CONNECT_SUCCESS中获得连接对象UsbDeviceConnection,接下来便是新建一个线程向USB接口中写入数据,类似下面这样:

//发送数据

new Thread(new Runnable() {

@Override

public void run() {

//发送数据

String message = "我是大神";

boolean flag=mUSBHelper.writeMessage(message,mUsbDeviceConnection,null);

if(flag){

LogUtil.i("发送成功");

}else{

LogUtil.i("发送失败");

}

}

}).start();

写数据的方法已经在USBHelper的

/**写数据**/

public boolean writeMessage(String message,UsbDeviceConnection connection,String charsetName)

方法中封装好了,大家对照着调用就行。

最后,当我们USB通讯已经用完了,需要在界面销毁时关闭USB,类似下面这样:

@Override

protected void onDestroy() {

//关闭USB

mUSBHelper.close(mUsbDeviceConnection);

super.onDestroy();

}

这样的话,一个完成的USB连接通讯就讲完了。当然,USBHelper中还有很多其他方法,大家有时间也可以看看。

五. 项目结构图

84127aa396f2

项目结构图.png

六. USBHelper 源码

下面给出USBHelper源码: