" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)讀寫USB串口數(shù)據(jù)

 更新時間:2022年09月19日 10:17:55   作者:zhoupuxian  
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)讀寫USB串口數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Android實(shí)現(xiàn)讀寫USB串口數(shù)據(jù)的具體代碼,供大家參考,具體內(nèi)容如下

最近在研究USB方面的內(nèi)容;先后做了關(guān)于Android讀寫HID、串口設(shè)備的DEMO。本文比較簡單,主要介紹的是Android實(shí)現(xiàn)讀取串口數(shù)據(jù)的功能

廢話不多說,先看一下業(yè)務(wù)層是如何調(diào)用的;如圖:

首先,監(jiān)聽USB連接狀況,當(dāng)USB 進(jìn)行請求USB權(quán)限,當(dāng)USB權(quán)限申請成功,進(jìn)行調(diào)用打開Usb設(shè)備的方法;當(dāng)監(jiān)聽到USB斷開,進(jìn)行關(guān)閉連接;

這是向串口寫入數(shù)據(jù)的方法;

本DEMO主要使用Handle進(jìn)行數(shù)據(jù)各個線程之間的數(shù)據(jù)傳到,以及USB連接讀寫情況的反饋;

下面直接上代碼:
連接USB設(shè)備的代碼

public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
? ? {
? ? ? ? this.usbDeviceConnection = usbDeviceConnection;
? ? ? ? usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //獲取USB設(shè)備接口
? ? ? ? if (usbDeviceConnection == null) //判斷USB設(shè)備鏈路是否為空
? ? ? ? {
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (!usbDeviceConnection.claimInterface(usbInterface,true)) //USB設(shè)備鏈路綁定獲取到的接口
? ? ? ? {
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? int numberEndpoints = usbInterface.getEndpointCount(); //獲取USB設(shè)備接口的數(shù)據(jù)傳輸通道數(shù)量
? ? ? ? for (int num = 0; num <= numberEndpoints-1; num++)
? ? ? ? {
? ? ? ? ? ? UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

? ? ? ? ? ? switch (usbEndpoint.getType())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //USB控制傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
? ? ? ? ? ? ? ? ? ? controlUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB塊傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_BULK:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkOutUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸出通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkInUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸入通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB中斷傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_INT:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intOutUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intInUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if (bulkOutUsbEndpoint != null && bulkInUsbEndpoint != null) //如果USB塊傳輸模式輸入輸通道都不為空出
? ? ? ? {
? ? ? ? ? ? //USB連接成功
? ? ? ? ? ? connect = true;
? ? ? ? ? ? //獲取到USB設(shè)備的ID、VID、PID
? ? ? ? ? ? String usbData = "Name:"+usbDevice.getDeviceName()+"\nID:"+usbDevice.getDeviceId()+" ? ?VID:"+usbDevice.getVendorId()+" ? ?PID:"+usbDevice.getProductId();
? ? ? ? ? ? mes = new Message();
? ? ? ? ? ? mes.obj = usbData;
? ? ? ? ? ? mes.what = MyHandler.USB_CONNECT_SUCCESS;
? ? ? ? ? ? myHandler.sendMessage(mes);
? ? ? ? ? ? threadReadData.start(); //開啟接收數(shù)據(jù)線程
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? //USB連接失敗
? ? ? ? ? ? connect = false;
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? }
? ? }

這個代碼有點(diǎn)多,可能看的不太清楚,我刪減一下,是這樣的

public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
? ? {
? ? ? ? this.usbDeviceConnection = usbDeviceConnection;
? ? ? ? usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //獲取USB設(shè)備接口
? ? ??
? ? ? ? int numberEndpoints = usbInterface.getEndpointCount(); //獲取USB設(shè)備接口的數(shù)據(jù)傳輸通道數(shù)量
? ? ? ? for (int num = 0; num <= numberEndpoints-1; num++)
? ? ? ? {
? ? ? ? ? ? UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

? ? ? ? ? ? switch (usbEndpoint.getType())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //USB控制傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
? ? ? ? ? ? ? ? ? ? controlUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB塊傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_BULK:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkOutUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸出通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkInUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸入通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB中斷傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_INT:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intOutUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intInUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ?
? ? }

設(shè)備打開之后,就可以進(jìn)行讀寫了;

Android 讀取串口數(shù)據(jù)

public String readData()
? ? {
? ? ? ? byte[] tempByte = new byte[4096];
? ? ? ?
? ? ? ? int i = usbDeviceConnection.bulkTransfer(bulkInUsbEndpoint,tempByte,tempByte.length,100);//讀取數(shù)據(jù),100為超時時間,接收的數(shù)據(jù)為數(shù)組類型
? ?
? ? ? ? //將接收的數(shù)組轉(zhuǎn)為字符串并返回
? ? ? ? byte[] messageByte = new byte[i];
? ? ? ? System.arraycopy(tempByte,0, messageByte,0, i);
? ? ? ? return new String(messageByte);
? ? }

這里主要通過調(diào)用谷歌提供的bulkTransfer方法進(jìn)行的,傳遞的參數(shù)分別有endpoint,要讀取的數(shù)據(jù)長度,和放要讀取的數(shù)據(jù)的數(shù)組,超時時間

有了讀,當(dāng)然也需要寫,向串口寫入數(shù)據(jù);代碼如下:

public boolean send(String message)
? ? {
? ? ??
? ? ? ? byte[] messageBytes = message.getBytes(); //字符串轉(zhuǎn)為數(shù)組
? ? ? ? int result = usbDeviceConnection.bulkTransfer(bulkOutUsbEndpoint,messageBytes,messageBytes.length,100);//發(fā)送數(shù)據(jù),發(fā)送轉(zhuǎn)換為數(shù)組后的數(shù)據(jù),超時時間為100毫秒
? ? ? ? if ((result >= 0)) //發(fā)送數(shù)據(jù)返回值大于等于0代表發(fā)送成功
? ? ? ? {
? ? ? ? ? ? //向信息處理中心發(fā)送“發(fā)送成功”的信息,并將信息內(nèi)容傳遞過去
? ? ? ? ? ?
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? //發(fā)送失敗
? ? ? ? ? ? connect = false;
? ? ? ? ? ? return false;
? ? ? ? }
? ? }

傳輸數(shù)據(jù)的方式是用Handler;以下是Handler類的寫法

public void handleMessage(@NonNull Message msg)
? ? {
? ? ? ? switch (msg.what)
? ? ? ? {
? ? ? ? ? ? case USB_CONNECT_SUCCESS: ?//USB設(shè)備連接成功
? ? ? ? ? ? ? ? MyHandler.USB_CONNECT_STATE ?= true; //連接狀態(tài)改變?yōu)閠rue
? ? ? ? ? ? ? ? bt_send.setEnabled(true); //發(fā)送控件可以使用
? ? ? ? ? ? ? ? bt_sendTiming.setEnabled(true);
? ? ? ? ? ? ? ? bt_send.setTextColor(Color.BLACK); //定時發(fā)送控件可以使用
? ? ? ? ? ? ? ? bt_sendTiming.setTextColor(Color.BLACK);?
? ? ? ? ? ? ? ? tv_usbDataShow.setText(msg.obj.toString()); //填充意圖發(fā)送過來的信息
? ? ? ? ? ? ? ? Toast.makeText(context,"連接成功",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case USB_CONNECT_FAILED: //USB設(shè)備連接失敗
? ? ? ? ? ? ? ? MyHandler.USB_CONNECT_STATE ?= false;
? ? ? ? ? ? ? ? bt_send.setEnabled(false);
? ? ? ? ? ? ? ? bt_sendTiming.setEnabled(false);
? ? ? ? ? ? ? ? bt_send.setTextColor(Color.GRAY);
? ? ? ? ? ? ? ? bt_sendTiming.setTextColor(Color.GRAY);
? ? ? ? ? ? ? ? bt_sendTiming.setText("定時發(fā)送");
? ? ? ? ? ? ? ? tv_usbDataShow.setText("未連接設(shè)備");
? ? ? ? ? ? ? ? mainActivity.closeAll(); //連接斷開或連接失敗,執(zhí)行關(guān)閉所有連接和對象的方法
? ? ? ? ? ? ? ? Toast.makeText(context,"斷開連接",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case OUTPUT: ?//發(fā)送消息
? ? ? ? ? ? ? ? if (messageShowNeedRoll(tv_sendMessageShow) != 0) tv_sendMessageShow.scrollTo(0, messageShowNeedRoll(tv_sendMessageShow));//如果TextView填充滿可使用高度就滾動到最新更新處
? ? ? ? ? ? ? ? tv_sendMessageShow.append("[TX]"+gteNowDate()+": "+msg.obj.toString()+"\n"); //給控件填充意圖發(fā)送來的信息
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case INPUT: ?//接收消息
? ? ? ? ? ? ? ? if (messageShowNeedRoll(tv_receiveMessageShow) != 0) tv_receiveMessageShow.scrollTo(0, messageShowNeedRoll(tv_receiveMessageShow));
? ? ? ? ? ? ? ? tv_receiveMessageShow.append("[RX]"+gteNowDate()+": "+msg.obj.toString()+"\n");
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }

主要代碼已展示完畢,接下來展示具體代碼

先看USB類,如下:

public class UsbCDC
{
? ? private boolean connect; //USB連接狀態(tài)
? ? private UsbInterface usbInterface; //USB設(shè)備的物理接口

? ? //控制傳輸模式通道
? ? private UsbEndpoint controlUsbEndpoint;
? ? //塊傳輸模式通道
? ? private UsbEndpoint bulkInUsbEndpoint;
? ? private UsbEndpoint bulkOutUsbEndpoint;
? ? //中斷傳輸模式通道
? ? private UsbEndpoint intInUsbEndpoint;
? ? private UsbEndpoint intOutUsbEndpoint;

? ? private UsbDeviceConnection usbDeviceConnection; //USB設(shè)備連接鏈路,用來進(jìn)行設(shè)備通訊

? ? private Message mes; //信息包

? ? private MyHandler myHandler;//信息處理中心對象
? ? UsbCDC(MyHandler myHandler)
? ? {
? ? ? ? this.myHandler = myHandler;
? ? }

? ? /**
? ? ?* 向USB設(shè)備發(fā)送數(shù)據(jù)
? ? ?* @param message 要發(fā)送的數(shù)據(jù),字符串類型
? ? ?* @return 數(shù)據(jù)發(fā)送結(jié)果,true代表發(fā)送成功
? ? ?*/
? ? public boolean send(String message)
? ? {
? ? ? ? if (this.usbDeviceConnection == null) //判斷USB鏈路是否獲取到,不為空才能進(jìn)行數(shù)據(jù)發(fā)送
? ? ? ? {
? ? ? ? ? ? //如果USB鏈路為空,執(zhí)行該作用域代碼
? ? ? ? ? ? connect = false;
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return false;
? ? ? ? }
? ? ? ? byte[] messageBytes = message.getBytes(); //字符串轉(zhuǎn)為數(shù)組
? ? ? ? int result = usbDeviceConnection.bulkTransfer(bulkOutUsbEndpoint,messageBytes,messageBytes.length,100);//發(fā)送數(shù)據(jù),發(fā)送轉(zhuǎn)換為數(shù)組后的數(shù)據(jù),超時時間為100毫秒
? ? ? ? if ((result >= 0)) //發(fā)送數(shù)據(jù)返回值大于等于0代表發(fā)送成功
? ? ? ? {
? ? ? ? ? ? //向信息處理中心發(fā)送“發(fā)送成功”的信息,并將信息內(nèi)容傳遞過去
? ? ? ? ? ? mes = new Message();
? ? ? ? ? ? mes.obj = new String(messageBytes);
? ? ? ? ? ? mes.what = MyHandler.OUTPUT;
? ? ? ? ? ? myHandler.sendMessage(mes);
? ? ? ? ? ? return true;
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? //發(fā)送失敗
? ? ? ? ? ? connect = false;
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return false;
? ? ? ? }
? ? }

? ? /**
? ? ?* 接收數(shù)據(jù)
? ? ?* @return 接收的數(shù)據(jù)內(nèi)容
? ? ?*/
? ? public String readData()
? ? {
? ? ? ? byte[] tempByte = new byte[4096];
? ? ? ? if (usbDeviceConnection == null) //判斷USB連接鏈路是否為空,不為空才能進(jìn)行數(shù)據(jù)接收
? ? ? ? {
? ? ? ? ? ? connect = false;
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? int i = usbDeviceConnection.bulkTransfer(bulkInUsbEndpoint,tempByte,tempByte.length,100);//讀取數(shù)據(jù),100為超時時間,接收的數(shù)據(jù)為數(shù)組類型
? ? ? ? if (i < 0) //小于0代表接收失敗或未接收到數(shù)據(jù),接收結(jié)果也受USB設(shè)備的影響
? ? ? ? {
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? //將接收的數(shù)組轉(zhuǎn)為字符串并返回
? ? ? ? byte[] messageByte = new byte[i];
? ? ? ? System.arraycopy(tempByte,0, messageByte,0, i);
? ? ? ? return new String(messageByte);
? ? }

? ? /**
? ? ?* 設(shè)置USB設(shè)備的波特率,方法內(nèi)涉及算法等;
? ? ?* @param paramInt 要設(shè)置波特率的數(shù)值
? ? ?* @return 設(shè)置結(jié)果,true代表設(shè)置成功
? ? ?*/
? ? public boolean configUsb(int paramInt)
? ? {
? ? ? ? if (usbDeviceConnection != null)
? ? ? ? {
? ? ? ? ? ? byte[] arrayOfByte = new byte[8];
? ? ? ? ? ? usbDeviceConnection.controlTransfer(192, 95, 0, 0, arrayOfByte, 8, 1000);
? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 161, 0, 0, null, 0, 1000);
? ? ? ? ? ? long l1 = 1532620800 / paramInt;
? ? ? ? ? ? for (int i = 3; ; i--)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if ((l1 <= 65520L) || (i <= 0))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? long l2 = 65536L - l1;
? ? ? ? ? ? ? ? ? ? int j = (short) (int) (0xFF00 & l2 | i);
? ? ? ? ? ? ? ? ? ? int k = (short) (int) (0xFF & l2);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(192, 149, 9496, 0, arrayOfByte, 8, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 154, 1304, 80, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 161, 20511, 55562, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? usbDeviceConnection.controlTransfer(64, 164, 0, 0, null, 0, 1000);
? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? l1 >>= 3;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else ?return false;
? ? }

? ? /**
? ? ?* 獲取收發(fā)數(shù)據(jù)的通道
? ? ?* @param usbDevice USB設(shè)備
? ? ?* @param usbDeviceConnection USB連接鏈路
? ? ?*/
? ? public void openCDC(UsbDevice usbDevice, UsbDeviceConnection usbDeviceConnection)
? ? {
? ? ? ? this.usbDeviceConnection = usbDeviceConnection;
? ? ? ? usbInterface = usbDevice.getInterface(findCDC(usbDevice)); //獲取USB設(shè)備接口
? ? ? ? if (usbDeviceConnection == null) //判斷USB設(shè)備鏈路是否為空
? ? ? ? {
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (!usbDeviceConnection.claimInterface(usbInterface,true)) //USB設(shè)備鏈路綁定獲取到的接口
? ? ? ? {
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ? int numberEndpoints = usbInterface.getEndpointCount(); //獲取USB設(shè)備接口的數(shù)據(jù)傳輸通道數(shù)量
? ? ? ? for (int num = 0; num <= numberEndpoints-1; num++)
? ? ? ? {
? ? ? ? ? ? UsbEndpoint usbEndpoint = usbInterface.getEndpoint(num);

? ? ? ? ? ? switch (usbEndpoint.getType())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //USB控制傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
? ? ? ? ? ? ? ? ? ? controlUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB塊傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_BULK:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkOutUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸出通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? bulkInUsbEndpoint = usbEndpoint; //USB塊傳輸模式輸入通道
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? //USB中斷傳輸模式通道
? ? ? ? ? ? ? ? case UsbConstants.USB_ENDPOINT_XFER_INT:
? ? ? ? ? ? ? ? ? ? switch (usbEndpoint.getDirection())
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_OUT:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intOutUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? case UsbConstants.USB_DIR_IN:
? ? ? ? ? ? ? ? ? ? ? ? ? ? intInUsbEndpoint = usbEndpoint;
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if (bulkOutUsbEndpoint != null && bulkInUsbEndpoint != null) //如果USB塊傳輸模式輸入輸通道都不為空出
? ? ? ? {
? ? ? ? ? ? //USB連接成功
? ? ? ? ? ? connect = true;
? ? ? ? ? ? //獲取到USB設(shè)備的ID、VID、PID
? ? ? ? ? ? String usbData = "Name:"+usbDevice.getDeviceName()+"\nID:"+usbDevice.getDeviceId()+" ? ?VID:"+usbDevice.getVendorId()+" ? ?PID:"+usbDevice.getProductId();
? ? ? ? ? ? mes = new Message();
? ? ? ? ? ? mes.obj = usbData;
? ? ? ? ? ? mes.what = MyHandler.USB_CONNECT_SUCCESS;
? ? ? ? ? ? myHandler.sendMessage(mes);
? ? ? ? ? ? threadReadData.start(); //開啟接收數(shù)據(jù)線程
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? //USB連接失敗
? ? ? ? ? ? connect = false;
? ? ? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);
? ? ? ? }
? ? }

? ? /**
? ? ?* USB接收數(shù)據(jù)線程
? ? ?*/
? ? private Thread threadReadData = new Thread(new Runnable()
? ? {
? ? ? ? String message = "";
? ? ? ? @Override
? ? ? ? public void run()
? ? ? ? {
? ? ? ? ? ? while (connect) //USB處于連接狀態(tài)就循環(huán)執(zhí)行
? ? ? ? ? ? {
? ? ? ? ? ? ? ? String temMes = readData(); //獲取到接收到的字符串
? ? ? ? ? ? ? ? if (temMes != null)?
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //如果接收到的數(shù)據(jù)不為空,就一直拼接,因?yàn)檫@些可能屬于同一組數(shù)據(jù)(除非USB設(shè)備發(fā)送頻率小于我們設(shè)置的超時時間100毫秒)
? ? ? ? ? ? ? ? ? ? message = message+temMes;
? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //接收到的數(shù)據(jù)為空了,表示該組數(shù)據(jù)接收完整了,就可以發(fā)送給消息處理中心進(jìn)行處理了
? ? ? ? ? ? ? ? ? ? if (!message.equals("")) //接收到的數(shù)據(jù)要不為空,不然沒意義
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? mes = new Message();
? ? ? ? ? ? ? ? ? ? ? ? mes.obj = message;
? ? ? ? ? ? ? ? ? ? ? ? mes.what = MyHandler.INPUT;
? ? ? ? ? ? ? ? ? ? ? ? myHandler.sendMessage(mes);
? ? ? ? ? ? ? ? ? ? ? ? message = "";
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? });

? ? /**
? ? ?* 獲取USB可以收發(fā)數(shù)據(jù)的接口號
? ? ?* @param usbDevice USB設(shè)備
? ? ?* @return USB可以收發(fā)數(shù)據(jù)的接口號
? ? ?*/
? ? private int findCDC(UsbDevice usbDevice)
? ? {
? ? ? ? int interfaceCount = usbDevice.getInterfaceCount(); //獲取USB設(shè)備接口數(shù)量
? ? ? ? for (int count = 0; count < interfaceCount; ++count)
? ? ? ? {
? ? ? ? ? ? //遍歷獲取到的接口進(jìn)行判斷是否為收發(fā)數(shù)據(jù)的接口,是就返回該接口號
? ? ? ? ? ? if (usbDevice.getInterface(count).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return count;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 如果獲取到的所有接口沒有我們需要的就返回-1
? ? ? ? return -1;
? ? }

? ? ?/**
? ? ?* 關(guān)閉USB連接、鏈路、數(shù)據(jù)通道等
? ? ?*/
? ? public void close()
? ? {
? ? ? ? connect = false; //連接狀態(tài)為false
? ? ? ? usbDeviceConnection.releaseInterface(usbInterface); //USB設(shè)備鏈路解綁接口
? ? ? ? usbDeviceConnection.close(); //關(guān)閉USB設(shè)備鏈路
? ? ? ? usbDeviceConnection = null; //USB設(shè)備鏈路賦值為空
? ? ? ? bulkOutUsbEndpoint = null; //輸出通道賦值為空
? ? ? ? bulkInUsbEndpoint = null; //輸入通道賦值為空
? ? }

}

接下來是連接USB類與業(yè)務(wù)層的中樞,HANDLER類:

package com.jlkj.lsk.usb_host;

import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyHandler extends Handler
{

? ? public static final int OUTPUT = 0; //發(fā)送消息
? ? public static final int INPUT = 1; //接收消息

? ? public static final int USB_CONNECT_SUCCESS = 2; //USB設(shè)備連接成功
? ? public static final int USB_CONNECT_FAILED = 3; //USB設(shè)備連接失敗或斷開連接

? ? public static boolean USB_CONNECT_STATE = false; //當(dāng)前USB設(shè)備連接狀態(tài)

? ? private Button bt_send,bt_sendTiming;?
? ? private TextView tv_sendMessageShow,tv_receiveMessageShow,tv_usbDataShow;
? ? private Context context; //上下文
? ? private MainActivity mainActivity;
? ? MyHandler(TextView tv_sendMessageShow, TextView tv_receiveMessageShow, TextView tv_usbDataShow, Button bt_send, Button bt_sendTiming, Context context,MainActivity mainActivity)
? ? {
? ? ? ? this.bt_send = bt_send;
? ? ? ? this.tv_sendMessageShow = tv_sendMessageShow;
? ? ? ? this.tv_receiveMessageShow = tv_receiveMessageShow;
? ? ? ? this.tv_usbDataShow = tv_usbDataShow;
? ? ? ? this.bt_sendTiming = bt_sendTiming;
? ? ? ? this.context = context;
? ? ? ? this.mainActivity = mainActivity;
? ? }

? ? @Override
? ? public void handleMessage(@NonNull Message msg)
? ? {
? ? ? ? switch (msg.what)
? ? ? ? {
? ? ? ? ? ? case USB_CONNECT_SUCCESS: ?//USB設(shè)備連接成功
? ? ? ? ? ? ? ? MyHandler.USB_CONNECT_STATE ?= true; //連接狀態(tài)改變?yōu)閠rue
? ? ? ? ? ? ? ? bt_send.setEnabled(true); //發(fā)送控件可以使用
? ? ? ? ? ? ? ? bt_sendTiming.setEnabled(true);
? ? ? ? ? ? ? ? bt_send.setTextColor(Color.BLACK); //定時發(fā)送控件可以使用
? ? ? ? ? ? ? ? bt_sendTiming.setTextColor(Color.BLACK);?
? ? ? ? ? ? ? ? tv_usbDataShow.setText(msg.obj.toString()); //填充意圖發(fā)送過來的信息
? ? ? ? ? ? ? ? Toast.makeText(context,"連接成功",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case USB_CONNECT_FAILED: //USB設(shè)備連接失敗
? ? ? ? ? ? ? ? MyHandler.USB_CONNECT_STATE ?= false;
? ? ? ? ? ? ? ? bt_send.setEnabled(false);
? ? ? ? ? ? ? ? bt_sendTiming.setEnabled(false);
? ? ? ? ? ? ? ? bt_send.setTextColor(Color.GRAY);
? ? ? ? ? ? ? ? bt_sendTiming.setTextColor(Color.GRAY);
? ? ? ? ? ? ? ? bt_sendTiming.setText("定時發(fā)送");
? ? ? ? ? ? ? ? tv_usbDataShow.setText("未連接設(shè)備");
? ? ? ? ? ? ? ? mainActivity.closeAll(); //連接斷開或連接失敗,執(zhí)行關(guān)閉所有連接和對象的方法
? ? ? ? ? ? ? ? Toast.makeText(context,"斷開連接",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case OUTPUT: ?//發(fā)送消息
? ? ? ? ? ? ? ? if (messageShowNeedRoll(tv_sendMessageShow) != 0) tv_sendMessageShow.scrollTo(0, messageShowNeedRoll(tv_sendMessageShow));//如果TextView填充滿可使用高度就滾動到最新更新處
? ? ? ? ? ? ? ? tv_sendMessageShow.append("[TX]"+gteNowDate()+": "+msg.obj.toString()+"\n"); //給控件填充意圖發(fā)送來的信息
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case INPUT: ?//接收消息
? ? ? ? ? ? ? ? if (messageShowNeedRoll(tv_receiveMessageShow) != 0) tv_receiveMessageShow.scrollTo(0, messageShowNeedRoll(tv_receiveMessageShow));
? ? ? ? ? ? ? ? tv_receiveMessageShow.append("[RX]"+gteNowDate()+": "+msg.obj.toString()+"\n");
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? }

? ? /**
? ? ?* 返回格式化后的當(dāng)前時間
? ? ?* @return 當(dāng)前時間字符串形式
? ? ?*/
? ? private String gteNowDate()
? ? {
? ? ? ? SimpleDateFormat sdf = new SimpleDateFormat();// 格式化時間
? ? ? ? sdf.applyPattern("HH:mm:ss");// 時:分:秒
? ? ? ? Date date = new Date();// 獲取當(dāng)前時間戳
? ? ? ? return sdf.format(date); //返回格式化后的時間戳
? ? }

? ? /**
? ? ?* 判斷當(dāng)前TextView是否已經(jīng)填充滿控件可使用高度,如果高度已滿就滾動需要的距離高度
? ? ?* @param textView 需要判斷的TextView控件
? ? ?* @return 已滿就返回對應(yīng)高度,否則就返回0
? ? ?*/
? ? private int messageShowNeedRoll(TextView textView)
? ? {
? ? ? ? int offset = textView.getLineCount() * textView.getLineHeight(); //添加的textview數(shù)量 x 字體高度
? ? ? ? if (offset > textView.getHeight()) return offset - tv_receiveMessageShow.getHeight(); //如果乘積大于控件高度就返回需要滾動的距離
? ? ? ? else return 0; //小于就返回0
? ? }

}

監(jiān)聽USB連接狀況的廣播類,如下:

package com.jlkj.lsk.usb_host;

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.UsbManager;
import android.widget.TextView;
import android.widget.Toast;
import java.util.HashMap;

public class UsbMonitor extends BroadcastReceiver //繼承USB廣播對象
{

? ? private static final String ACTION_USB_PERMISSION = "com.spark.teaching.answertool.USB_PERMISSION"; //USB設(shè)備的操作權(quán)限,可自定義
? ? //private static final String ACTION_USB_PERMISSION = "android.USB"; //USB設(shè)備的操作權(quán)限,可自定義
? ? private int VID = 1155; //USB設(shè)備生產(chǎn)廠商ID,用來區(qū)分選擇目標(biāo)USB設(shè)備,如果不是該ID的USB設(shè)備,不對其進(jìn)行操作
? ? private int PID = 1155; //USB設(shè)備生產(chǎn)廠商ID,用來區(qū)分選擇目標(biāo)USB設(shè)備,如果不是該ID的USB設(shè)備,不對其進(jìn)行操作
? ? private UsbController usbController; //USB動作管理接口
? ? private UsbManager usbManager; //USB狀態(tài)、管理對象
? ? private UsbDevice usbDevice; //USB設(shè)備
? ? private Context context; //上下文
? ? private TextView tv_usbDeviceDataShow; //USB信息數(shù)據(jù)展示控件

? ? /**
? ? ?* 數(shù)據(jù)初始化
? ? ?* @param usbController usb控制器接口
? ? ?* @param context 上下文
? ? ?* @param tv_usbDeviceDataShow USB信息數(shù)據(jù)展示控件
? ? ?*/
? ? UsbMonitor(UsbController usbController,Context context,TextView tv_usbDeviceDataShow)
? ? {
? ? ? ? this.usbController = usbController;
? ? ? ? this.context = context;
? ? ? ? this.tv_usbDeviceDataShow = tv_usbDeviceDataShow;
? ? }

? ? /**
? ? ?* 注冊USB廣播監(jiān)聽、USB權(quán)限
? ? ?*/
? ? public void register()
? ? {
? ? ? ? if (this.context != null)
? ? ? ? {
? ? ? ? ? ? IntentFilter intentFilter = new IntentFilter(); //意圖過濾器
? ? ? ? ? ? intentFilter.addAction(ACTION_USB_PERMISSION); //添加USB設(shè)備的操作權(quán)限意圖
? ? ? ? ? ? intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); //添加設(shè)備接入意圖
? ? ? ? ? ? intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); //添加設(shè)備拔出意圖
? ? ? ? ? ? this.context.registerReceiver(this, intentFilter); //注冊添加的意圖
? ? ? ? ? ? usbManager = (UsbManager)this.context.getSystemService(Context.USB_SERVICE); //獲取USB設(shè)備管理

? ? ? ? ? ? if (usbManager != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? HashMap<String,UsbDevice> list = usbManager.getDeviceList(); //獲取USB設(shè)備,返回的是 UsbDevice 的Hash列表,里面是所有當(dāng)前連接主機(jī)的USB設(shè)備
? ? ? ? ? ? ? ? for (UsbDevice usbDevice : list.values()) //遍歷獲取到的UsbDevice
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if ((usbDevice.getVendorId() == VID)&&(usbDevice.getProductId() == PID)) //找到目標(biāo)USB設(shè)備
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? this.usbDevice = usbDevice;
? ? ? ? ? ? ? ? ? ? ? ? usbController.onDeviceInsert(this, usbManager,usbDevice); //執(zhí)行USB接入時接口
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? tv_usbDeviceDataShow.setText("不支持該設(shè)備"); //如果列表里面沒有目標(biāo)USB設(shè)備,執(zhí)行該操作
? ? ? ? ? ? }
? ? ? ? ? ? tv_usbDeviceDataShow.setText("未連接設(shè)備"); //如果沒有USB設(shè)備接入,執(zhí)行該操作
? ? ? ? }
? ? }

? ? /**
? ? ?* 請求打開此USB設(shè)備的權(quán)限
? ? ?* @param usbDevice usb設(shè)備
? ? ?*/
? ? public void requestOpenDevice(UsbDevice usbDevice)
? ? {
? ? ? ? if (usbManager != null)
? ? ? ? {
? ? ? ? ? ? if (usbManager.hasPermission(usbDevice))//如果有該USB設(shè)備的操作權(quán)限
? ? ? ? ? ? {
? ? ? ? ? ? ? ? usbController.onDeviceOpen(this,usbManager,usbDevice);//連接USB設(shè)備(打開USB設(shè)備)
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? usbManager.requestPermission(usbDevice,PendingIntent.getBroadcast(context, 666, new Intent(ACTION_USB_PERMISSION), 0));//如果沒有USB操作權(quán)限則請求權(quán)限
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? /**
? ? ?* 注銷USB廣播監(jiān)聽
? ? ?*/
? ? public void unregister()
? ? {
? ? ? ? if (context != null)
? ? ? ? {
? ? ? ? ? ? context.unregisterReceiver(this); //注銷USB設(shè)備廣播監(jiān)聽
? ? ? ? ? ? context = null;
? ? ? ? ? ? usbManager = null;
? ? ? ? ? ? usbController = null;
? ? ? ? }
? ? }

? ? /**
? ? ?* 廣播事務(wù)處理中心
? ? ?* @param context 上下文
? ? ?* @param intent 意圖
? ? ?*/
? ? @Override
? ? public void onReceive(Context context, Intent intent)
? ? {
? ? ? ? if (intent.getExtras() != null && !intent.getExtras().isEmpty())
? ? ? ? {
? ? ? ? ? ? usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); //獲取意圖中的USB設(shè)備
? ? ? ? ? ? switch(intent.getAction())
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case UsbManager.ACTION_USB_DEVICE_ATTACHED: //USB設(shè)備接入
? ? ? ? ? ? ? ? ? ? Toast.makeText(context, "設(shè)備接入", Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? if ((usbDevice.getVendorId() == VID)&&(usbDevice.getProductId() == PID)) usbController.onDeviceInsert(this, usbManager,usbDevice); //找到目標(biāo)USB設(shè)備,執(zhí)行USB設(shè)備接入時接口
? ? ? ? ? ? ? ? ? ? else tv_usbDeviceDataShow.setText("不支持該設(shè)備"); //未找到目標(biāo)USB設(shè)備
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case UsbManager.ACTION_USB_DEVICE_DETACHED: //USB設(shè)備拔出
? ? ? ? ? ? ? ? ? ? Toast.makeText(context, "設(shè)備斷開", Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? usbController.onDevicePullOut(this,usbManager,usbDevice); //執(zhí)行USB設(shè)備拔出時接口
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case UsbMonitor.ACTION_USB_PERMISSION: //請求USB設(shè)備操作權(quán)限
? ? ? ? ? ? ? ? ? ? if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? //同意USB權(quán)限
? ? ? ? ? ? ? ? ? ? ? ? usbController.onDeviceOpen(this,usbManager,usbDevice); //執(zhí)行連接USB設(shè)備接口
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? //拒絕USB權(quán)限
? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(context, "拒絕USB權(quán)限!", Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? Toast.makeText(this.context,"請檢查USB設(shè)備!",Toast.LENGTH_LONG).show();
? ? ? ? }
? ? }

}

接口類 UsbController

public interface UsbController
{

? ? ?/**
? ? ?* USB設(shè)備接入時的接口
? ? ?* @param usbMonitor USB監(jiān)聽廣播對象
? ? ?* @param usbManager USB狀態(tài)、管理對象
? ? ?* @param usbDevice USB設(shè)備對象
? ? ?*/
? ? void onDeviceInsert(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);

? ? //USB設(shè)備拔出時的接口
? ? void onDevicePullOut(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);

? ? //連接USB設(shè)備(打開USB設(shè)備)的接口
? ? void onDeviceOpen(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice);
? ??
}

activity類

package com.jlkj.lsk.usb_host;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity implements UsbController
{
? ? private Timer timer; //計時器對象
? ? private TimerTask timerTask; //計時器任務(wù)對象

? ? private UsbCDC usbCDC; //當(dāng)前連接的USB設(shè)備對象
? ? private MyHandler myHandler; //消息處理中心對象
? ? private UsbMonitor usbMonitor; //USB監(jiān)聽廣播對象
? ? private TextView m_tv_sendMessageShow,m_tv_receiveMessageShow,m_tv_usbDataShow,m_tv_porterShow;
? ? private EditText m_et_messageText,m_et_time;
? ? private Button m_bt_send,m_bt_sendTiming,m_bt_clean,m_tv_porterSet;

? ? @Override
? ? protected void onCreate(Bundle savedInstanceState)
? ? {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? initView(); //實(shí)例化當(dāng)前頁面控件
? ? ? ? initData(); //加載初始數(shù)據(jù)

? ? ? ? m_bt_send.setOnClickListener(new View.OnClickListener()
? ? ? ? {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //開啟新線程進(jìn)行數(shù)據(jù)發(fā)送
? ? ? ? ? ? ? ? new Thread(new Runnable()
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void run()
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? usbCDC.send(m_et_messageText.getText().toString()); //向當(dāng)前連接的USB設(shè)備發(fā)送消息
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }).start();
? ? ? ? ? ? }
? ? ? ? });

? ? ? ? m_bt_clean.setOnClickListener(new View.OnClickListener()
? ? ? ? {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? m_tv_sendMessageShow.setText(""); //清除發(fā)送的消息文本
? ? ? ? ? ? ? ? m_tv_receiveMessageShow.setText(""); //清除接收的消息文本
? ? ? ? ? ? ? ? m_tv_sendMessageShow.scrollTo(0, 0); //發(fā)送的消息文本回滾到最頂部
? ? ? ? ? ? ? ? m_tv_receiveMessageShow.scrollTo(0, 0); //接收的消息文本回滾到最頂部
? ? ? ? ? ? }
? ? ? ? });

? ? ? ? m_bt_sendTiming.setOnClickListener(new View.OnClickListener()
? ? ? ? {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //判斷計時器是否為空,不為就代表正在執(zhí)行計時任務(wù),就停止當(dāng)前任務(wù)
? ? ? ? ? ? ? ? if (timer != null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? timer.cancel(); //停止計時器
? ? ? ? ? ? ? ? ? ? timer = null; //計時器設(shè)為空
? ? ? ? ? ? ? ? ? ? m_bt_sendTiming.setTextColor(Color.BLACK); //改變定時發(fā)送控件的顏色
? ? ? ? ? ? ? ? ? ? m_bt_sendTiming.setText("定時發(fā)送"); //控件 恢復(fù)為“定時發(fā)送”
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? //如果為空,就開始定時發(fā)送任務(wù)
? ? ? ? ? ? ? ? ? ? if (!m_et_time.getText().toString().equals("")) //獲取定時任務(wù)的時間間隔
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? timer = new Timer(); //創(chuàng)建定時器
? ? ? ? ? ? ? ? ? ? ? ? timerTask = new TimerTask() //創(chuàng)建定時任務(wù)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run()
? ? ? ? ? ? ? ? ? ? ? ? ? ? { ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //定時任務(wù)要執(zhí)行的內(nèi)容
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? usbCDC.send(m_et_messageText.getText().toString());
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? };
? ? ? ? ? ? ? ? ? ? ? ? new Thread(new Runnable() //開啟新線程執(zhí)行 開啟計時器
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? ? ? ? ? public void run()
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //開啟計時器
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? timer.schedule(timerTask,0,Integer.parseInt(m_et_time.getText().toString()));
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }).start();
? ? ? ? ? ? ? ? ? ? ? ? m_bt_sendTiming.setTextColor(Color.RED);
? ? ? ? ? ? ? ? ? ? ? ? m_bt_sendTiming.setText("停止"); //計時器開始后“定時發(fā)送”控件就改變顏色和字體
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? //判斷計時器是否為空,如果為空,就執(zhí)行該作用域內(nèi)容
? ? ? ? ? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this,"定時不能為空",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });

? ? ? ? m_tv_porterSet.setOnClickListener(new View.OnClickListener()
? ? ? ? {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(View v)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //展示設(shè)置波特率的diaog對象
? ? ? ? ? ? ? ? setPorter();
? ? ? ? ? ? }
? ? ? ? });
? ? }

? ? @Override
? ? public void onDeviceInsert(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
? ? {
? ? ? ? usbMonitor.requestOpenDevice(usbDevice); //請求USB連接權(quán)限
? ? }

? ? @Override
? ? public void onDevicePullOut(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
? ? {
? ? ? ?closeAll(); //執(zhí)行關(guān)閉所有連接的方法
? ? ? ?myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED); //向消息中心發(fā)送 斷開連接 信息
? ? }

? ? @Override
? ? public void onDeviceOpen(UsbMonitor usbMonitor, UsbManager usbManager, UsbDevice usbDevice)
? ? {
? ? ? ? usbCDC = new UsbCDC(myHandler); //創(chuàng)建USB連接的對象
? ? ? ? UsbDeviceConnection connection = usbManager.openDevice(usbDevice); //獲取此USB鏈路
? ? ? ? usbCDC.openCDC(usbDevice, connection); //連接USB設(shè)備(打開USB設(shè)備)
? ? }

? ? @Override
? ? protected void onDestroy()
? ? {
? ? ? ? super.onDestroy();
? ? ? ? closeAll();//執(zhí)行關(guān)閉所有連接的方法
? ? ? ? myHandler.sendEmptyMessage(MyHandler.USB_CONNECT_FAILED);//向消息中心發(fā)送 斷開連接 信息
? ? }

? ? //關(guān)閉所有連接
? ? public void closeAll()
? ? {
? ? ? ? if (usbCDC != null)
? ? ? ? {
? ? ? ? ? ? usbCDC.close();
? ? ? ? ? ? usbCDC = null;
? ? ? ? }
? ? ? ? if (timer != null)
? ? ? ? {
? ? ? ? ? ? timer.cancel();
? ? ? ? ? ? timer = null;
? ? ? ? }
? ? }

? ? //展示設(shè)置波特率dialog的對象,用一個AlertDialog讓用戶進(jìn)行選擇比特率
? ? private void setPorter()
? ? {
? ? ? ? final String[] items = {"2400","4800","9600","19200","38400","57600","115200","230400","460800","1700000","2300000","3400000"};
? ? ? ? AlertDialog.Builder listDialog = new AlertDialog.Builder(MainActivity.this);
? ? ? ? listDialog.setTitle("設(shè)置波特率");
? ? ? ? listDialog.setItems(items, new DialogInterface.OnClickListener()
? ? ? ? {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onClick(DialogInterface dialog, int which)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //判斷當(dāng)前USB設(shè)備是否連接,連接之后才可以設(shè)置波特率
? ? ? ? ? ? ? ?if (usbCDC != null)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?boolean porter = usbCDC.configUsb(Integer.parseInt(items[which])); //執(zhí)行設(shè)置波特率的對象,返回true代表設(shè)置成功
? ? ? ? ? ? ? ? ? ?m_tv_porterShow.setText(porter ? "波特率:"+items[which]:"波特率:9600"); //設(shè)置波特率對象返回true才改變控件字體,否則設(shè)置失敗,不改變控件字體
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? //判斷當(dāng)前USB設(shè)備是否連接,未連接則提示 設(shè)備未連接
? ? ? ? ? ? ? ? ? ?Toast.makeText(MainActivity.this,"設(shè)備未連接",Toast.LENGTH_LONG).show();
? ? ? ? ? ? ? ?}
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? listDialog.show(); //展示dialog
? ? }

? ? //加載數(shù)據(jù)
? ? private void initData()
? ? {
? ? ? ? myHandler = new MyHandler(m_tv_sendMessageShow,m_tv_receiveMessageShow,m_tv_usbDataShow,m_bt_send,m_bt_sendTiming,this,MainActivity.this); //實(shí)例化消息處理中心
? ? ? ? usbMonitor = new UsbMonitor(this,this,m_tv_usbDataShow); //實(shí)例化USB廣播監(jiān)聽
? ? ? ? usbMonitor.register(); //注冊USB廣播監(jiān)聽,注冊之后,才可以正常監(jiān)聽USB設(shè)備
? ? }

? ? //實(shí)例化控件
? ? private void initView()
? ? {
? ? ? ? m_tv_receiveMessageShow = (TextView)findViewById(R.id.m_tv_receiveMessageShow);
? ? ? ? m_tv_receiveMessageShow.setMovementMethod(ScrollingMovementMethod.getInstance());
? ? ? ? m_tv_sendMessageShow = (TextView)findViewById(R.id.m_tv_sendMessageShow);
? ? ? ? m_tv_sendMessageShow.setMovementMethod(ScrollingMovementMethod.getInstance());
? ? ? ? m_tv_usbDataShow = (TextView)findViewById(R.id.m_tv_usbDataShow);
? ? ? ? m_et_messageText = (EditText)findViewById(R.id.m_et_messageText);
? ? ? ? m_et_time = (EditText)findViewById(R.id.m_et_time);
? ? ? ? m_bt_sendTiming = (Button)findViewById(R.id.m_bt_sendTiming);
? ? ? ? m_bt_clean = (Button)findViewById(R.id.m_bt_clean);
? ? ? ? m_bt_send = (Button)findViewById(R.id.m_bt_send);
? ? ? ? m_tv_porterShow = (TextView)findViewById(R.id.m_tv_porterShow);
? ? ? ? m_tv_porterSet = (Button)findViewById(R.id.m_bt_porterSet);
? ? }

}

這個比較初級,接下來,我會再出一個精簡版本;詳細(xì)探討Android讀取USB串口、HID設(shè)備的實(shí)現(xiàn);我把這兩個集成在了一起,并打包成了arr文件,這個庫可以自動識別USB 串口或USB hid ,當(dāng)連接成功,就可以自動讀寫;代碼比這個更為精簡;接下來我會慢慢的記錄下來。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Flutter 控制屏幕旋轉(zhuǎn)的實(shí)現(xiàn)

    Flutter 控制屏幕旋轉(zhuǎn)的實(shí)現(xiàn)

    這篇文章主要介紹了Flutter 控制屏幕旋轉(zhuǎn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Android使用Item Swipemenulistview實(shí)現(xiàn)仿QQ側(cè)滑刪除功能

    Android使用Item Swipemenulistview實(shí)現(xiàn)仿QQ側(cè)滑刪除功能

    大家都用過QQ,肯定有人好奇QQ滑動刪除Item的效果是怎樣實(shí)現(xiàn)的,其實(shí)我們使用Swipemenulistview就可以簡單的實(shí)現(xiàn)。這篇文章主要介紹了Android使用ItemSwipemenulistview實(shí)現(xiàn)仿QQ側(cè)滑刪除功能,需要的朋友可以參考下
    2017-02-02
  • Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動回繞效果

    Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動回繞效果

    這篇文章主要為大家詳細(xì)介紹了Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動回繞效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android 動態(tài)高斯模糊效果教程

    Android 動態(tài)高斯模糊效果教程

    本文主要介紹Android 動態(tài)高斯模糊效果教程,這里整理了詳細(xì)的資料及實(shí)例實(shí)現(xiàn)代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • Android實(shí)現(xiàn)單選按鈕

    Android實(shí)現(xiàn)單選按鈕

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)單選按鈕,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Android AS創(chuàng)建自定義布局案例詳解

    Android AS創(chuàng)建自定義布局案例詳解

    這篇文章主要介紹了Android AS創(chuàng)建自定義布局案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Android中兩個類讓你再也不用實(shí)現(xiàn)onActivityResult()

    Android中兩個類讓你再也不用實(shí)現(xiàn)onActivityResult()

    這篇文章主要給大家介紹了關(guān)于Android中兩個類讓你再也不用實(shí)現(xiàn)onActivityResult()的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2018-08-08
  • Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多

    Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多

    這篇文章主要介紹了Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-07-07
  • 解決Android Studio XML編輯界面不顯示下面的Text和Design選項(xiàng)卡

    解決Android Studio XML編輯界面不顯示下面的Text和Design選項(xiàng)卡

    這篇文章主要介紹了解決Android Studio XML編輯界面不顯示下面的Text和Design選項(xiàng)卡,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android實(shí)現(xiàn)圖片滾動效果

    Android實(shí)現(xiàn)圖片滾動效果

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)圖片滾動效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評論