前言
在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中还有很多其他方法,大家有时间也可以看看。
五. 项目结构图
项目结构图.png
六. USBHelper 源码
下面给出USBHelper源码: