安卓USB開發教程 USB Host
USB Host(主機模式)
當 Android 裝置處於 USB 主機模式時,它充當 USB 主機,為匯流排供電,並列舉連線的 USB 裝置。Android 3.1 及更高版本支援 USB 主機模式。
API 概述
Class | Description |
---|---|
UsbManager |
負責列舉和與連線的 USB 裝置通訊 |
UsbDevice |
表示連線的 USB 裝置並且包含訪問其標識資訊,介面和端點的方法 |
UsbInterface |
表示 USB 裝置的介面,它定義了裝置的一組功能。 裝置可以具有一個或多個介面進行通訊。 |
UsbEndpoint |
表示介面端點,它是該介面的通訊通道。 介面可以有一個或多個端點,並且通常具有與裝置進行雙向通訊的輸入和輸出端點。 |
UsbDeviceConnection |
表示與裝置的連線,該裝置在端點上傳輸資料。 該類允許您以同步方式或非同步方式來回傳送資料。 |
UsbRequest |
表示通過UsbDeviceConnection與裝置通訊的非同步請求。 |
UsbConstants |
定義與Linux核心的linux / usb / ch9.h中的定義對應的USB常量。 |
在大多數情況下,與 USB 裝置通訊時需要使用所有這些類(UsbRequest 只在非同步方式通訊的時候需要)。通常,會獲取一個 UsbManager 來檢索所需的 UsbDevice。當獲取到裝置時,需要查詢合適的 UsbInterface 與介面中用於通訊的UsbEndpoint
。一旦獲取到正確的端點,開啟一個 UsbDeviceConnection
與
USB 裝置通訊。
Android Manifest 要求
下面的清單描述了在使用 USB host API 函式前需要新增到應用清單檔案的內容:
1. 由於並非所有安卓裝置被授權支援 USB host API 函式,因此需要包含一個 <uses-feature>
元素來宣告你的應用使用 android.hardware.usb.host功能。
2. 設定應用的最低 SDK 版本為 API 級別 12 或更高。USB host API 函式在更早的 API 級別中不存在。
3. 如果你希望應用收到 USB 裝置插入的通知,請在主活動中為 android.hardware.usb.action.USB_DEVICE_ATTACHED 意圖指定<intent-filter> 和 <meta-data> 元素對。<meta-data> 元素指向一個外部 XML 資原始檔,它宣告瞭要檢測的裝置的資訊。
4. 在 XML 資原始檔中,為你想過濾的 USB 裝置宣告 <usb-device>元素。下表描述了 <usb-device> 的屬性。
通常,如果要過濾特定的裝置使用廠商和產品 ID,如果要過濾一組 USB 裝置使用 USB 類、子類和協議,如大容量儲存類和數位相機。
你可以指定這些屬性中的一個或者全部,不指定屬性匹配任何 USB 裝置,因此在應用需要時才進行指定:
vendor-id
product-id
class
subclass
protocol (device or interface)
將資原始檔儲存在 res/xml/ 目錄中。資原始檔名(不含 .xml 副檔名)必須與您在 <meta-data> 元素中指定的檔名相同。XML 資原始檔的格式在下面的示例中。
Manifest 與資原始檔示例
<manifest ...>
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
...
<application>
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
使用裝置
在這種情況下,當使用者將 USB 裝置連線到 Android 裝置時,Android 系統可以確定應用程式是否對連線的裝置感興趣。如果是這樣,您可以根據需要建立與裝置的通訊。為此,您的應用程式必須:
1.通過使用 intent filter 在使用者連線裝置時收到通知或通過列舉已連線的 USB 裝置來發現 USB 裝置。
2. 請求使用者連線 USB 裝置的許可權,如果尚未獲得。
3. 通過在相應的介面端點上讀寫資料與 USB 裝置進行通訊。
發現裝置
應用程式可以通過使用intent filter 在使用者連線裝置時收到通知或通過列舉已連線的 USB 裝置來發現 USB 裝置。如果您希望能夠讓應用程式自動檢測到所需的裝置,則使用 intent filter 非常有用。 如果要獲取所有連線的裝置列表,或者您的應用程式沒有為 intent 進行過濾,則列舉已連線的 USB 裝置的方法非常有用。
使用 intent filter(意圖過濾器)
要使您的應用程式發現一個特定的 USB 裝置,可以指定一個 intent filter 來過濾android.hardware.usb.action.USB_DEVICE_ATTACHED intent。 除了此 intent filter,您還需要指定一個資原始檔,該資原始檔指定USB裝置的屬性,如產品和供應商ID。 當使用者連線與 device filter 匹配的裝置時,系統會向他們顯示一個對話方塊,詢問他們是否要啟動應用程式。 如果使用者接受,應用程式自動獲得訪問裝置許可權,直到裝置斷開連線。
以下示例展示如何宣告 intent filter:
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
以下示例展示如何宣告相應資原始檔,其指定了感興趣的 USB 裝置。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" />
</resources>
在你的活動中,你可以像這樣從 intent 中獲取表示連線裝置的 UsbDevice :
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
列舉裝置
當應用程式執行時,如果應用程式有興趣檢查當前連線的所有 USB 裝置,它可以列舉匯流排裝置。使用 getDeviceList()
方法獲取所有已連線
USB 裝置的雜湊表,如果要從表中獲取裝置,通過作為鍵值傳入的
USB 裝置名。
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
UsbDevice device = deviceList.get("deviceName");
如果需要,還可以從雜湊表中獲取 iterator(迭代器),並逐個處理每個裝置:
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while(deviceIterator.hasNext()){
UsbDevice device = deviceIterator.next();
//your code
}
獲取與裝置進行通訊的許可權
在與USB裝置進行通訊之前,應用程式必須獲得使用者的許可。
Note:如果應用程式使用 intent filter 來發現連線時的 USB 裝置,則如果使用者允許您的應用程式處理 intent,則它將自動接收權限。如果沒有,您必須在連線到裝置之前在應用程式中明確請求許可權。
在某些情況下,顯式請求許可可能是必需的,例如當您的應用程式列舉已連線的USB裝置,然後要與其進行通訊時。在嘗試與之通信之前,您必須檢查訪問裝置的許可權。如果沒有,使用者拒絕訪問裝置的許可權時,您將收到 runtime 錯誤。
要明確獲得許可,首先建立一個廣播接收器。該接收器偵聽當您呼叫 requestPermission()
時獲得廣播的意圖。對 requestPermission()
的呼叫向使用者顯示一個對話方塊,請求連線到裝置的許可權。以下示例程式碼展示瞭如何建立廣播接收器:
private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
//call method to set up device communication
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
要註冊廣播接收器,在活動的 onCreate() 方法中新增如下程式碼:
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
...
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
要顯示請求使用者連線裝置許可權的對話方塊,呼叫 requestPermission()
方法:
UsbDevice device;
...
mUsbManager.requestPermission(device, mPermissionIntent);
當使用者響應對話方塊時,廣播接收器收到包含額外值EXTRA_PERMISSION_GRANTED 的 intent,這是表示答案的布林值。 在連線裝置之前,請檢查這個額外值是否為 true。
與裝置通訊
與USB裝置的通訊可以是同步或非同步的。在任一情況下,您應該建立一個新執行緒來執行所有資料傳輸,才不會阻塞UI執行緒。要正確建立與裝置的通訊,您需要獲得要進行通訊的裝置的相應的UsbInterface 和UsbEndpoint
,並使用
在此端點上發送請求。一般來說,您的程式碼應該:UsbDeviceConnection
1. 檢查UsbDevice 物件的屬性,如產品 ID,供應商 ID或裝置類,以確定是否要與裝置進行通訊;
2. 當您確定要與裝置通訊時,請找到與合適的UsbEndpoint 進行通訊的相應UsbInterface
。介面可以具有一個或多個端點,並且通常會具有用於雙向通訊的輸入和輸出端點;
3. 找到正確的端點時,在該端點上開啟一個UsbDeviceConnection
;
4. 使用bulkTransfer()
或controlTransfer() 方法提供在端點上傳輸的資料。您應該在另一個執行緒中執行此步驟,以防止阻塞主
UI 執行緒。有關在 Android 中使用執行緒的更多資訊,請參閱 Processes
and Threads。
以下程式碼片段是進行同步資料傳輸的簡單方法。您的程式碼應該有更多的邏輯來正確找到正確的介面和端點進行通訊,並且還應該在與主UI執行緒不同的執行緒中進行資料傳輸:
private Byte[] bytes;
private static int TIMEOUT = 0;
private boolean forceClaim = true;
...
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = mUsbManager.openDevice(device);
connection.claimInterface(intf, forceClaim);
connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread
要非同步傳送資料,使用 UsbRequest
類來 initialize 和 queue
一個非同步請求,然後呼叫 requestWait()
等待結果。
終止與裝置通訊
當你與裝置通訊完成或者裝置拔出時,呼叫 releaseInterface()
與
close()
方法關閉 UsbInterface
與 UsbDeviceConnection。
為了監聽拔除事件,如下所示建立廣播接收器:
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
// call your method that cleans up and closes communication with the device
}
}
}
};
執行的應用程式而不是廣播到所有應用。在應用程式中而不是 manifest 中建立廣播接收器允許應用在執行時只處理拔除事件。通過這種方式,廣播事件只會傳送到當前正在
原文連結:https://developer.android.com/guide/topics/connectivity/usb/host.html
相關文章
- 安卓USB開發教程 USB Host 與 Accessory安卓
- 安卓USB開發教程 USB Accessory安卓
- Libusb開發教程 USB裝置程式開發
- garmin USB: linux USB host驅動Linux
- 安卓之USB主機(Host)與配件(Accessory)模式安卓模式
- Android 系統使用USB OTG功能/開啟USB Host API功能AndroidOTGAPI
- android USB host程式設計Android程式設計
- Mac開發安卓時,SDK Tools下找不到Google Usb DriverMac安卓Go
- Libusb開發教程 API介紹與使用API
- HarmonyOS USB DDK助你輕鬆實現USB驅動開發
- linux usb 子系統(二)- host driverLinux
- vivo X6 usb除錯在哪 vivo X6開啟USB除錯教程除錯
- Windows下USB磁碟開發系列二:列舉系統中所有USB裝置Windows
- USB專殺工具:USBclean for MacMac
- linux usb 驅動開發 抓包工具Linux
- HarmonyOS 裝置管理開發:USB 服務開發指導
- 安卓手機怎樣開啟USB除錯模式(圖文介紹)安卓除錯模式
- usb 3.0 linux libusb 問題Linux
- USB-C:新一代USB介面
- USB-A, Micro, lightning and USB-C
- USB 端點與USB HUB的關係
- _get_usbfs_fd libusb couldn‘t open the usb 許可權不夠
- [OpenWrt]軟路由H28K開啟USB無線教程路由
- USB PD和USB TYPE-C 的區別
- usb驅動開發1之學習準備
- linux下 libusb使用--開啟usb裝置進行通訊Linux
- USB主機
- USB-CyAPIAPI
- 高通USB overviewView
- usb協議協議
- C++ Qt開發:StatusBar底部狀態列元件C++QT元件
- Android USB 轉串列埠通訊開發基本流程Android串列埠
- USB開發速成-我最真實的經驗!(轉)
- STM32-USB學習筆記(一) USB基礎筆記
- Win10如何新增usb快捷刪除鍵?Win10新增usb快捷刪除鍵教程Win10
- Qt usb通訊QT
- usb-descriptor(一 )
- usb-descriptor(二)