一、什么是USB
USB就是通用串行总线(Universal Serial Bus)的缩写,用于规范主从通信。USB接口支持设备的即插即用和热插拔功能。
与USB有关的OTG既是On-The-Go,主要用于各种不同的设备或移动设备件间的链接和数据交换。
二、Android的USB相关API
包:android.hardware.usb
类:UsbManager/UsbDevice/UsbInterface/UsbEndPoint/UsbDeviceConnection/UsbRequest/UsbConstants/UsbAccessory
获取UsbManager:UsbManager manager = (UsbManager)getSystemService(Context.USB_SERVICE);
三、Android设备与USB设备
第一种模式Host Mode:Android设备作为Host,向Usb设备供电,并进行数据传输;
第一种模式Accessory Mode:Usb设备作为Host,向Android设备供电,并进行数据传输;
四、例子(可以枚举设备/点击设备建立连接/接收数据/发送数据)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usbhelper"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-feature android:name="android.hardware.usb.host" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".UsbReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</receiver>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usbhelper"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-feature android:name="android.hardware.usb.host" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".UsbReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</receiver>
</application>
</manifest>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usbhelper"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-feature android:name="android.hardware.usb.host" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".UsbReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity.java
package com.example.usbhelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
@SuppressLint("NewApi")
public class MainActivity extends Activity {
private Button send = null;
private Button receive = null;
private Button list = null;
private ListView information = null;
private EditText content = null;
private TextView result = null;
private Handler mHandler = null;
private ArrayList<UsbDevice> devicesList = null;
private ArrayList<HashMap<String, Object>> showDevices = null;
private SimpleAdapter adapter = null;
private boolean isRunning = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
// super.handleMessage(msg);
int what = msg.what;
switch (what) {
case 0: {
String string = msg.obj.toString();
result.setText(result.getText().toString() + "\n" + string);
}
break;
default:
break;
}
}
};
initData();
}
private UsbManager mUsbManager = null;
private void initData() {
findViewsById();
showDevices = new ArrayList<HashMap<String, Object>>();
devicesList = new ArrayList<UsbDevice>();
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
registerUsbReceiver();
initListView();
}
private PendingIntent mPermissionIntent = null;
private void registerUsbReceiver() {
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
}
private void findViewsById() {
send = (Button) findViewById(R.id.btn_send_main);
receive = (Button) findViewById(R.id.btn_receive_main);
content = (EditText) findViewById(R.id.et_content_main);
result = (TextView) findViewById(R.id.tv_result_main);
list = (Button) findViewById(R.id.btn_list_main);
information = (ListView) findViewById(R.id.lv_devices_main);
send.setOnClickListener(mOnClickListener);
receive.setOnClickListener(mOnClickListener);
list.setOnClickListener(mOnClickListener);
information.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
mUsbManager.requestPermission(devicesList.get(arg2),
mPermissionIntent);
}
});
}
private void listTheDevice() {
if (mUsbManager == null) {
return;
}
HashMap<String, UsbDevice> devices = mUsbManager.getDeviceList();
Iterator<UsbDevice> iterator = devices.values().iterator();
showDevices.clear();
devicesList.clear();
while (iterator.hasNext()) {
UsbDevice device = iterator.next();
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("device_id", device.getDeviceId());
map.put("device_name", device.getDeviceName());
showDevices.add(map);
devicesList.add(device);
}
if (showDevices.size() > 0) {
adapter = new SimpleAdapter(MainActivity.this, showDevices,
R.layout.item, new String[] { "device_id", "device_name" },
new int[] { R.id.device_id, R.id.device_name });
information.setAdapter(adapter);
}
Toast.makeText(this, "设备数:" + devicesList.size(), Toast.LENGTH_SHORT)
.show();
}
private void initListView() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("device_id", "测试数据");
map.put("device_name", "测试数据");
showDevices.add(map);
adapter = new SimpleAdapter(MainActivity.this, showDevices,
R.layout.item, new String[] { "device_id", "device_name" },
new int[] { R.id.device_id, R.id.device_name });
information.setAdapter(adapter);
}
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
int id = arg0.getId();
switch (id) {
case R.id.btn_list_main:
listTheDevice();
break;
case R.id.btn_send_main: {
String message = content.getText().toString();
if (message != null && message.length() > 0) {
new Thread(new SendRunnable(message.getBytes()));
}
}
break;
case R.id.btn_receive_main: {
if (isRunning) {
isRunning = false;
} else {
isRunning = true;
new Thread(new ReceiveRunnable()).start();
}
}
break;
default:
Toast.makeText(MainActivity.this, "我真的不知道你对我做了什么",
Toast.LENGTH_SHORT).show();
break;
}
}
};
private class ReceiveRunnable implements Runnable {
public void run() {
byte[] buffer = new byte[64];
while (isRunning) {
mDeviceConnection.bulkTransfer(epin, buffer, buffer.length, 0);
Message msg = new Message();
msg.what = 0;
msg.obj = new String(buffer);
mHandler.sendMessage(msg);
System.out.println("received true");
}
}
}
private class SendRunnable implements Runnable {
private byte[] buffer;
public SendRunnable(byte[] buffer) {
this.buffer = buffer;
}
public void run() {
int length = mDeviceConnection.bulkTransfer(epout, buffer,
buffer.length, 0);
if (length > 0) {
mDeviceConnection.bulkTransfer(epin, buffer, buffer.length, 0);
Message msg = new Message();
msg.what = 0;
msg.obj = new String(buffer);
mHandler.sendMessage(msg);
}
}
}
// mUsbManager.requestPermission(device, mPermissionIntent);
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private UsbDeviceConnection mDeviceConnection = null;
private UsbEndpoint epin = null;
private UsbEndpoint epout = null;
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
} else if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice mUsbDevice;
mUsbDevice = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (mUsbDevice != null) {
// call method to set up device communication
UsbInterface intf = mUsbDevice.getInterface(0);
epin = intf.getEndpoint(0);
epout = intf.getEndpoint(1);
mDeviceConnection = mUsbManager
.openDevice(mUsbDevice);
mDeviceConnection.claimInterface(intf, true);
}
} else {
Log.d("UsbHelper", "permission denied for device "
+ mUsbDevice.getDeviceName());
}
}
}
}
};
}
UsbReceiver.java
package com.example.usbhelper;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.sax.StartElementListener;
public class UsbReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Intent intent = new Intent(arg0, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(intent);
}
}
五、小结
USB通信是一种不会磨灭的通信,你懂的。随着物联网的到来和发展,WIFI/蓝牙/Zigbee火起来的,但随着物联网的进一步发展,USB或者类似的通信协议也将会得到空前的应用,因为,组件化会成为智能产品快速研发的关键,即插即用,安全可靠。