Android USB通信入门篇

Android USB开发模式

Android中USB有两种开发模式,一种是host模式,另一种是accessory模式,下面介绍一下这两种模式。

(1)Host模式:如图,此模式中,Android设备充当主机,给USB外部设备供电,常见的Host模式有:鼠标、键盘等。

(2)Accessory模式:如图,和Host模式相反,此模式中,usb设备充当主机,给android手机提供电源,常见的设备:无人机远程控制器等。

进入Hello World

配置AndroidManifest.xml文件中USB模式

在Android系统中,默认是关闭USB模式的,当我们将USB外部设备插入Android设备时,Android系统不会作出任何响应。如果我们要打开系统USB模式,需要在Android清单文件里使用<uses-feature/>标签声明响应的USB模式

Host模式

1
<uses-feature android:name="android.hardware.usb.host" />

Accessory模式

1
<uses-permission android:name="android.hardware.usb.accessory" />

配置USB设备插入的通知和相关USB设备的过滤

若我们希望在插入USB设备时,Android系统能接收到提示性通知,则需要在Android组件<Activity/>中配置<intent-filter/><meta-data/>标签配置相关信息,<intent-filter/>中配置我们要接收的相关类型的信息通知,<meta-data/>配置我们需要检测的指定的设备,标签内容对应一个xml资源文件,里面配置我们指定的USB设备。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<activity android:name=".ui.ChoiceModelActivity">

<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!--host模式下通知的过滤-->
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<!--host模式下指定过滤设备的配置文件-->
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />


<!--accessory模式下通知的过滤-->
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<!--accessory模式下指定过滤设备的配置文件-->
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/device_filter" />

</activity>

其中xml资源文件的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<rescources xmlns:android="http://schemas.android.com/apk/res/android">
<!--host模式-->
<usb-device
class=""
vendor-id=""
product-id=""
protoclo=""
subclass="" />

<!--accessory模式-->
<usb-accessory
model="xxx"
manufacturer="xxx" />

Android设备与USB设备连接和通信

无论是Host模式还是Accessory模式,在进行检测获取USB设备时,都需要用到UsbManager类,只是调用不同的方法而已。如下:

Host模式

1)获取UsbManager
2)通过usbManager获取连接到的USB外部设备
3)获取USB设备引用,通过usbManager检测是否有对应权限,若无则请求权限,通过广播接收权限信息获取情况
4)与USB设备进行通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
public static final String action_usb_permission = "cn.appblog.usb.permission";

public void hostModel(Context context) {

//获取UsbManager
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

//获取usb设备列表
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();

Set<Map.Entry<String, UsbDevice>> entries = deviceList.entrySet();

UsbDevice mUsbDevice = null;

for (Map.Entry<String, UsbDevice> entry : entries) {
UsbDevice value = entry.getValue();
String key = entry.getKey();

if (filterDevice(key, value)) {//判断是否是我们要连接的usb设备
mUsbDevice = value;
break;
}
}

if (usbManager.hasPermission(mUsbDevice)) {//检测是否有usb权限
requestPermission(mUsbDevice);
} else {
connect(mUsbDevice);
}

}

/**
* 请求usb权限
* @param usbManager
* @param parcelable
*/
public void requestPermission(Parcelable parcelable, UsbManager usbManager) {
UsbDevice usbDevice = (UsbDevice) parcelable;
if (!usbManager.hasPermission(usbDevice)) {
IntentFilter intentFilter = new IntentFilter(action_usb_permission);
registerReceiver(mMyBroadcastReceiver, intentFilter);
PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, new Intent(action_usb_permission), 0);
usbManager.requestPermission(usbDevice, broadcast);
} else {
Toast.makeText(context, "already have permission", Toast.LENGTH_SHORT).show();
}
}
}

public boolean connect(UsbDevice mUsbDevice) {
if (mUsbDevice != null) {
UsbInterface anInterface = mUsbDevice.getInterface(0);
mUsbDeviceConnection = mUsbManager.openDevice(mUsbDevice);//连接usb设备
if (mUsbDeviceConnection == null) {
Toast.makeText(mContext, "mUsbDeviceConnection can't be null", Toast.LENGTH_SHORT).show();
return false;
}
if (mUsbDeviceConnection.claimInterface(anInterface, true)) {
Toast.makeText(mContext, "找到USB接口", Toast.LENGTH_SHORT).show();
int endpointCount = anInterface.getEndpointCount();
for (int i = 0; i < endpointCount; i++) {
UsbEndpoint endpoint = anInterface.getEndpoint(i);
if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (UsbConstants.USB_DIR_IN == endpoint.getDirection()) {
mUsbEndpoint_in = endpoint;//获取读数据通道
} else {
mUsbEndpoint_out = endpoint;//获取写数据通道
}
}
}
return true;
} else {
mUsbDeviceConnection.close();//关闭连接
Toast.makeText(mContext, "找不到USB接口", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mContext, "mUsbDevice can't be null", Toast.LENGTH_SHORT).show();
}
return false;
}

/**
* 从usb通信设备中读取数据
* @return
*/
public byte[] readData() {
int inMax = mUsbEndpoint_in.getMaxPacketSize();
byte[] bytes = new byte[inMax];
ByteBuffer byteBuffer = ByteBuffer.allocate(inMax);
UsbRequest usbRequest = new UsbRequest();
usbRequest.initialize(mUsbDeviceConnection, mUsbEndpoint_in);
usbRequest.queue(byteBuffer, inMax);
if (mUsbDeviceConnection.requestWait() == usbRequest) {
bytes = byteBuffer.array();
}
return bytes;
}

/**
* 将数据写入到usb设备中
* @param bytes
*/
public void sendData(byte[] bytes) {
if (mUsbDeviceConnection == null) {
Toast.makeText(mContext, "mUsbDeviceConnection can't be null", Toast.LENGTH_SHORT).show();
return;
}
if (mUsbEndpoint_out == null) {
Toast.makeText(mContext, "mUsbEndpoint_out can't be null", Toast.LENGTH_SHORT).show();
return;
}

int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpoint_out, bytes, bytes.length, 1000);
if (i < 0) {
Toast.makeText(mContext, "failure to write", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "success to write", Toast.LENGTH_SHORT).show();
}
}

/**
* 权限广播接收器
*/
private BroadcastReceiver mMyBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action_usb_permission.equals(action)) {
synchronized (this) {
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (usbDevice != null) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
connect(usbDevice);
Toast.makeText(context, "success get permission", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "failure get permission", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, "the usbDevice be null", Toast.LENGTH_SHORT).show();
}
}
}
}
};

/**
* 筛选出我们想要的usb设备
* @param name
* @param usbDevice
* @return
*/
public boolean filterDevice(String name, UsbDevice usbDevice) {
// TODO: 2019/3/13 对应判断设备是否是我们要连接的设备
return false;
}

Accessory模式

Host模式差不多,大致步骤一样,只是相关类不同而已如下

1)获取UsbManager
2)通过usbManager获取连接到的USB外部设备UsbAccessory
3)获取USB设备引用,通过usbManager检测是否有对应权限,若无则请求权限,通过广播接收权限信息获取情况
4)与UsbAccessory设备进行通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
public static final String action_usb_permission = "cn.appblog.usb.permission";

private UsbManager usbManager;

public void hostAccessory(Context context) {

//获取UsbManager
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

//获取usb设备列表
UsbAccessory[] accessoryList = usbManager.getAccessoryList();

if (accessoryList == null || accessoryList.length <= = 0) {
Toast.makeText(context, "未查询到对应设备", Toast.LENGTH_SHORT).show();
return;
}

UsbAccessory mUsbAccessory = null;
for (UsbAccessory usbAccessory : accessoryList) {
if (filterDevice(usbAccessory)) {//判断是否使我们要连接的usb设备
break;
}
}

if (usbManager.hasPermission(mUsbAccessory)) {//检测是否有usb权限
requestPermission(mUsbAccessory);//请求usb权限
} else {
connect(mUsbAccessory);//连接usb设备
}

}

/**
* 请求usb权限
*
* @param usbManager
* @param parcelable
*/
public void requestPermission(Parcelable parcelable, UsbManager usbManager) {
UsbAccessory usbAccessory = (UsbAccessory) parcelable;
if (!usbManager.hasPermission(usbAccessory)) {
IntentFilter intentFilter = new IntentFilter(action_usb_permission);
registerReceiver(mMyBroadcastReceiver, intentFilter);
PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, new Intent(action_usb_permission), 0);
usbManager.requestPermission(usbAccessory, broadcast);
} else {
Toast.makeText(context, "already have permission", Toast.LENGTH_SHORT).show();
}
}

private FileInputStream mFileInputStream;

private FileOutputStream mFileOutputStream;

/**
* 连接设备
* @param usbAccessory
* @return
*/
public boolean connect(UsbAccessory usbAccessory) {
ParcelFileDescriptor parcelFileDescriptor = usbManager.openAccessory(usbAccessory);
if (parcelFileDescriptor != null) {
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();

mFileInputStream = new FileInputStream(fileDescriptor);

mFileOutputStream = new FileOutputStream(fileDescriptor);

}
return false;
}

/**
* 写入数据
* @param data
*/
public void write(byte[] data) {
try {
mFileOutputStream.write(data);
} catch (IOException e) {
e.printStackTrace();
}

}

/**
* 读取数据
*/
public void read() {
int max;//字节数据根据协议来确定
byte[] data = new byte[max];
mFileInputStream.read(data);
}


/**
* 权限广播接收器
*/
private BroadcastReceiver mMyBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action_usb_permission.equals(action)) {
synchronized (this) {
UsbAccessory usbAccessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (usbAccessory != null) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
connect(usbAccessory);
Toast.makeText(context, "success get permission", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "failure get permission", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, "the usbDevice be null", Toast.LENGTH_SHORT).show();
}
}
}
}
};

/**
* 筛选出我们想要的usb设备
*
* @param usbAccessory
* @return
*/
public boolean filterDevice(UsbAccessory usbAccessory) {
// TODO: 2019/3/13 对应判断设备是否是我们要连接的设备
return false;
}

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :