前言
在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
中添加如下权限:
<!-- 声明使用usb -->
<uses-feature
android:name="android.hardware.usb.host"
android:required="true" />
然后在 Androidmanifast.xml
中给要进行USB
连接的Activity
下添加usb
列表文件。假设我们要在MainActivity
中进行USB
连接,则在 Androidmanifast.xml
中的MainActivity
注册下添加以下代码:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- android设备的信息过滤 -->
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb" />
</activity>
主要是在Usb
连接相关的Activity
注册下添加下面的代码:
<!-- android设备的信息过滤 -->
<meta-data
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
文件内容大致如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="8746" product-id="1"/>
<usb-device vendor-id="5263" product-id="30329" />
<usb-device vendor-id="9168" product-id="3200" />
<usb-device vendor-id="6495" product-id="1" />
<usb-device vendor-id="2385" product-id="5734" />
</resources>
usb.xml
里面基本是放的一个Android
设备中所有USB
接口的信息了。以上代码中,一个<usb-device ......./>
即代表一个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);
//建立连接
Map<String,Object>map=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
接口信息列表,然后在建立连接:
Map<String,Object>map=mUSBHelper.connectProcess(6495,1);
中的参数6495
,1
可以通过插拔USB
接口,然后在mUSBHelper.registerUsb(new USBHelper.OnHotplugListener())
方法中的find(UsbDevice device)
中找到vendorId
和productId
。
然后USB
连接流程已经封装到了:
/**连接sub流程**/
public Map<String,Object> 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
源码:
网友评论