日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android OTG-HID的连接与通讯

發布時間:2023/12/8 Android 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android OTG-HID的连接与通讯 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、HID是什么?
  • 二、HID設備的連接過程
    • 1.配置Manifest
    • 2.HID設備的枚舉與連接
      • 1.設備枚舉
      • 2.查找接口
      • 3.指定通訊端點
      • 4.連接設備
    • 3.數據的發送與接收
      • 1.發送
      • 2.接收
  • 總結


前言

正在開發的項目中多有涉及到Android通過OTG-HID與設備終端通訊的需求,所以寫下本篇博客做個筆記。

如何進行USB接口的HID進行開發?網站上很多文章并不完善,這方便的也介紹的不多,我看了很多資料,借助網上的一些代碼,整理了以下信息,希望能給大家提供便捷。


一、HID是什么?

USB HID類是USB設備的一個標準設備類,包括的設備非常多。HID類設備定義它屬于人機交互操作的設備,用于控制計算機操作的一些方面,如USB鼠標、USB鍵盤、USB游戲操縱桿等。但HID設備類不一定要有人機接口,只要符合HID類別規范的設備都是HID設備。

二、HID設備的連接過程

1.配置Manifest

在Manifest中加入以下代碼

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

uses-feature是用來聲明一個app在運行時所依賴的外部的硬件或軟件特征(feature),此處是聲明Android設備必須能作為Host。uses-permission聲明Host權限。

2.HID設備的枚舉與連接

1.設備枚舉

HID設備一般通過Pid和Vid來枚舉。Pid和Vid由硬件廠商提供,也可以插在PC端通過PC端的設備管理器查看。

mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); HashMap<String,UsbDevice> usbDevices = mUsbManager.getDeviceList();Log.e(TAG,"usbDevices" + usbDevices.size()) ;for (UsbDevice usbDevice : usbDevices.values()) {if( (usbDevice.getProductId() == mPid && usbDevice.getVendorId() == mVid) ){mUsbDevice = usbDevice;hadEnum = true;Log.d(TAG, "find Device");break;}}

UsbManager是在android.hardware.usb包下的USB設備管理類,通過這個類的getDeviceList()方法來枚舉連接在android設備上USB設備。然后我們通過UsbDevice的getProductId()和getVendorId()方法獲取設備的Pid和Vid來找到我們的設備。

2.查找接口

private void findInterface() {if(mUsbDevice != null) {Log.d(TAG,"interfaceCounts = " + mUsbDevice.getInterfaceCount());for(int i = 0; i < mUsbDevice.getInterfaceCount() ; i++) {final UsbInterface intf = mUsbDevice.getInterface(i);Log.e(TAG,"usbClass = " + intf.getInterfaceClass());Log.e(TAG,"usbSubClass = " + intf.getInterfaceSubclass());Log.e(TAG,"usbProtocol = " + intf.getInterfaceProtocol());if(UsbConstants.USB_CLASS_HID == intf.getInterfaceClass()&& 0 ==intf.getInterfaceSubclass()&& 0 == intf.getInterfaceProtocol()) {mInterface = intf;break;}}}

一個USB設備下可能存在多個Interface,我們需要通過getInterfaceClass()方法獲取接口類型來判斷是否有支持HID通訊的接口,UsbConstants.USB_CLASS_HID同樣是android.hardware.usb包的一個全局變量。表示HID設備。Hid設備的InterfaceSubclass和InterfaceProtocol一般都為0。

/*** USB class for human interface devices (for example, mice and keyboards).*/public static final int USB_CLASS_HID = 3;

3.指定通訊端點

private void assignEndPoint() {if(mInterface != null ){for(int i = 0; i < mInterface.getEndpointCount() ; i++) {final UsbEndpoint ep = mInterface.getEndpoint(i);Log.d(TAG,"ep.getType() =" + ep.getType() );if(ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT){if(ep.getDirection() == UsbConstants.USB_DIR_IN){Log.d(TAG,"find mEpIn :MaxPacketSize = " + ep.getMaxPacketSize());mEpIn = ep;}else if(ep.getDirection() == UsbConstants.USB_DIR_OUT){Log.d(TAG,"find mEpOut :MaxPacketSize = " + ep.getMaxPacketSize());mEpOut = ep;}}}}}

同樣一個接口下可能多有點端點,我們也需要找到通訊端點,首先通過getType()方法獲取端點類型,我們這里只需要中斷類型(UsbConstants.USB_ENDPOINT_XFER_INT),然后通過getDirection() == UsbConstants.USB_DIR_IN來獲取輸入端點,通過ep.getDirection() == UsbConstants.USB_DIR_OUT獲取輸出端點。同時我們可以通過getMaxPacketSize獲取端點支持的最大包長。

4.連接設備

在獲取完接口和端點后就可以開始連接了,但是在連接之前還需要做一些權限的準備工作,因為Android的限制,在使用Usb設備之前需要用戶授權。
首先我們定義一個申請權限的Action:

private final String ACTION_USB_PERMISSION = "ACTION.USB_PERMISSION";

申請權限的結果是通過廣播返回的,所以我們需要定義一個廣播接收器并注冊。

private class USBReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 這里可以拿到插入的USB設備對象UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);switch(intent.getAction()) {case UsbManager.ACTION_USB_DEVICE_ATTACHED: // 插入USB設備Log.e(TAG, "USB插入");break;case UsbManager.ACTION_USB_DEVICE_DETACHED: // 拔出USB設備Log.e(TAG, "USB拔出");isUsbConnect = false;stopConnect();break;case ACTION_USB_PERMISSION:Log.e(TAG, "申請授權");if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {//user choose YES for your previously popup window asking for grant perssion // for this usb devicesynchronized(syncObj) {syncObj.notifyAll();}} else {//user choose NO for your previously popup window asking for grant perssion // for this usb devicesynchronized(syncObj) {syncObj.notifyAll();}}break;default:break;}}}private void registerUSBReceiver(Context mContext) {IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);mUsbReceiver = new USBReceiver();mContext.registerReceiver(mUsbReceiver, filter);}

由于項目需要,所以我貼的代碼還對設備的插入和拔出做了處理,如果你不需要可以不用監聽。

好了準備好之后我們就可以開始連接設備了。

private int openDevice() {if (mUsbDevice == null || mInterface == null) {return -16;}// 在open前判斷是否有連接權限;對于連接權限可以靜態分配,也可以動態分配權限,可以查閱相關資料PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);try {if (!mUsbManager.hasPermission(mUsbDevice)) {mUsbManager.requestPermission(mUsbDevice, pi);synchronized(syncObj){syncObj.wait();}if (!mUsbManager.hasPermission(mUsbDevice)) {return -17;}}UsbDeviceConnection conn = mUsbManager.openDevice(mUsbDevice);if(conn == null){return -18;}if(conn.claimInterface(mInterface,true)){mConnection = conn;return 0;}else {conn.close();return -18;}} catch (Exception e) {e.printStackTrace();return -18;}}

在連接前我們先確認一下是否有權限,如果沒有就通過requestPermission方法來申請權限,并在用戶授權結束后再次判斷一下是否已有權限,因為用戶如果點了拒絕,設備還是沒有權限。然后通過UsbManager.openDevice()來連接設備,最后通過UsbDeviceConnection .claimInterface()方法確認連接,至此我們的HID設備就正式連接完成了。

3.數據的發送與接收

設備連接完成之后,我們就可以通過先前獲取的發送、接收端點來進行通訊了。

1.發送

int transferred = mConnection.bulkTransfer(mEpOut, data, data.length, 1000);

四個參數分別代表:發送端點mEpOut、待發送數據、待發送數據長度、超時時間(ms),返回值為實際發送數據長度(失敗為-1)。
上文我們提到過端點有最大包長限制,實際使用中,超過最大包長android底層依然會給你做分包,但是數據超出過大,會存在數據丟失問題,所以建議大數據做分包發送處理。

2.接收

接收數據我們通過開啟一個線程循環接收。

private class RecvThread extends Thread {byte[] recv_buff = new byte[MaxPackSize];int recv_len;@Overridepublic void run() {super.run();while(true) {if(!isUsbConnect) {return;}try {recv_len = mConnection.bulkTransfer(mEpIn, recv_buff, recv_buff.length, 1000);if(recv_len > 0) {String hex = Util.byte2HexStr(recv_buff, 0, recv_len);for(int i = 0; i < recv_len; i++) {queue.offer(recv_buff[i]);}}} catch (Exception e) {e.printStackTrace();}}}}

四個參數分別代表:接收端點mEpIn、欲接收數據、欲接收數據長度、超時時間(ms),返回值為實際接收數據長度(失敗為-1)。我們這里按最大包長來接收。原因和發送一樣。


總結

以上就是今天要講的內容,本文僅僅介紹了Android設備通過OTG-HID協議和HID設備的簡單通訊,希望能對你有所幫助。

總結

以上是生活随笔為你收集整理的Android OTG-HID的连接与通讯的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。