具體步驟
發(fā)現(xiàn)設(shè)備
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
Map<String, UsbDevice> usbList = usbManager.getDeviceList();
官方注釋:
This class represents a USB device attached to the android device with the android device
acting as the USB host.
這個類代表了android所連接的usb設(shè)備尘奏。
打開設(shè)備
需要打開剛剛搜索到的usb設(shè)備饶囚。
一般來說,在沒有定制的android設(shè)備上首次訪問usb設(shè)備的時候唬格,默認我們是沒有訪問權(quán)限的鹃操,因此我們首先要判斷對當前要打開的usbDevice是否有訪問權(quán)限:
if (!usbManager.hasPermission(usbDevice)) {
usbPermissionReceiver = new UsbPermissionReceiver();
//申請權(quán)限
Intent intent = new Intent(ACTION_DEVICE_PERMISSION);
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION);
context.registerReceiver(usbPermissionReceiver, permissionFilter);
usbManager.requestPermission(usbDevice, mPermissionIntent);
}
需要聲明一個廣播UsbPermissionReceiver,當接受到授權(quán)成功的廣播后做一些其他處理抚垃。
private class UsbPermissionReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_DEVICE_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device.getDeviceName().equals(usbDevice.getDeviceName()) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
//授權(quán)成功,在這里進行打開設(shè)備操作
} else {
//授權(quán)失敗
}
}
}
}
}
}
接下來喷楣,要找到具有數(shù)據(jù)傳輸功能的接口UsbInterface,從它里面找到數(shù)據(jù)輸入和輸出端口UsbEndpoint鹤树,一般情況下铣焊,一個usbDevice有多個UsbInterface,我們需要的一般是第一個罕伯,所以:
usbInterface=usbDevice.getInterface(0);
同樣的曲伊,一個usbInterface有多個UsbEndpoint,有控制端口和數(shù)據(jù)端口等追他,因此我們需要根據(jù)類型和數(shù)據(jù)流向來找到需要的數(shù)據(jù)輸入和輸出兩個端口:
for (int index = 0; index < usbInterface.getEndpointCount(); index++) {
UsbEndpoint point = usbInterface.getEndpoint(index);
if (point.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (point.getDirection() == UsbConstants.USB_DIR_IN) {
usbEndpointIn = point;
} else if (point.getDirection() == UsbConstants.USB_DIR_OUT) {
usbEndpointOut = point;
}
}
}
最后坟募,才是真正的打開usb設(shè)備,我們需要和usb外設(shè)建立一個UsbDeviceConnection邑狸,官方注釋:
This class is used for sending and receiving data and control messages to a USB device.
UsbDeviceConnection的獲刃概础:
usbDeviceConnection = usbManager.openDevice(usbDevice);
數(shù)據(jù)傳輸
- 向usb外設(shè)發(fā)送數(shù)據(jù)
在第二步中,我們已經(jīng)獲取了數(shù)據(jù)的輸出端口usbEndpointIn单雾,我們向外設(shè)發(fā)送數(shù)據(jù)就是通過這個端口來實現(xiàn)的赚哗。
int ret = usbDeviceConnection.bulkTransfer(usbEndpointOut, data, data.length, DEFAULT_TIMEOUT);
bulkTransfer這個函數(shù)用于在給定的端口進行數(shù)據(jù)傳輸,第一個參數(shù)就是此次傳輸?shù)亩丝诠瓒眩@里我們用的輸出端口屿储,第二個參數(shù)是要發(fā)送的數(shù)據(jù),類型為字節(jié)數(shù)組渐逃,第三個參數(shù)代表要發(fā)送的數(shù)據(jù)長度够掠,最后一個參數(shù)是超時,返回值代表發(fā)送成功的字節(jié)數(shù)朴乖,如果返回-1祖屏,那就是發(fā)送失敗了。
- 接受usb外設(shè)發(fā)送來的數(shù)據(jù)
已經(jīng)找到了數(shù)據(jù)輸入端口usbEndpointIn买羞,因為數(shù)據(jù)的輸入是不定時的袁勺,因此我們可以另開一個線程,來專門接受數(shù)據(jù)畜普。
int inMax = inEndpoint.getMaxPacketSize();
ByteBuffer byteBuffer = ByteBuffer.allocate(inMax);
UsbRequest usbRequest = new UsbRequest();
usbRequest.initialize(connection, inEndpoint);
usbRequest.queue(byteBuffer, inMax);
if(connection.requestWait() == usbRequest){
byte[] retData = byteBuffer.array();
for(Byte byte1 : retData){
System.err.println(byte1);
}
}
注:理論上設(shè)備之間的連接已經(jīng)建立了期丰,也可以首發(fā)數(shù)據(jù)了,但是,我們大部分情況下還需要對usb串口進行一些配置钝荡,比如波特率,停止位,數(shù)據(jù)控制等街立,不然兩邊配置不同,收到的數(shù)據(jù)會亂碼埠通,具體怎么配置赎离,需要看串口芯片。
測試設(shè)備需求
- Android版本>3.2的設(shè)備
- OTG轉(zhuǎn)接線