Android實(shí)現(xiàn)讀寫USB串口數(shù)據(jù)
本文實(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),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Android使用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-02Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動回繞效果
這篇文章主要為大家詳細(xì)介紹了Android ViewPager實(shí)現(xiàn)智能無限循環(huán)滾動回繞效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07Android中兩個類讓你再也不用實(shí)現(xiàn)onActivityResult()
這篇文章主要給大家介紹了關(guān)于Android中兩個類讓你再也不用實(shí)現(xiàn)onActivityResult()的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-08-08Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多
這篇文章主要介紹了Android程序開發(fā)之Listview下拉刷新上拉(滑動分頁)加載更多的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07解決Android Studio XML編輯界面不顯示下面的Text和Design選項(xiàng)卡
這篇文章主要介紹了解決Android Studio XML編輯界面不顯示下面的Text和Design選項(xiàng)卡,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03