自 2025 年 3 月 27 日起,我們建議您使用 android-latest-release
而非 aosp-main
建構及貢獻 AOSP。詳情請參閱「Android 開放原始碼計畫變更」。
Android Open Accessory 1.0
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
Android USB 配件必須遵循 Android Open Accessory (AOA) 通訊協定,該協定定義了配件如何偵測 Android 裝置並設定通訊。配件應執行下列步驟:
- 等待並偵測已連線的裝置。
- 判斷裝置是否支援配件模式。
- 嘗試以配件模式啟動裝置 (如有需要)。
- 如果裝置支援 AOA,請與裝置建立通訊。
以下各節將說明如何實作這些步驟。
等待並偵測已連結的裝置
配件應持續檢查是否有連線的 Android 裝置。裝置連線時,配件應判斷裝置是否支援配件模式。
判斷是否支援配件模式
注意:連接配件不需要啟用 USB 偵錯功能,但開發期間可能需要 ADB。詳情請參閱
偵錯考量因素。
Android 裝置連線時,可能會有下列三種狀態:
- 支援 Android 配件模式,且已處於配件模式。
- 支援 Android 配件模式,但未處於配件模式。
- 不支援 Android 配件模式。
在初始連線期間,配件應檢查已連線裝置的 USB 裝置描述元版本、供應商 ID 和產品 ID。供應商 ID 應與 Google ID (0x18D1
) 相符。如果裝置已處於配件模式,產品 ID 應為 0x2D00
或 0x2D01
,且配件可使用自己的通訊通訊協定,透過大量傳輸端點與裝置建立通訊 (裝置不需要在配件模式下啟動)。
注意: 0x2D00
僅供支援配件模式的 Android 裝置使用。0x2D01
是為支援配件模式和 Android Debug Bridge (ADB) 通訊協定的裝置保留,可為 ADB 提供含有兩個大量端點的第二個介面。如果您要在電腦上模擬配件,可以使用這些端點來偵錯配件應用程式。一般來說,除非配件在裝置上實作 ADB 的傳遞功能,否則請勿使用這個介面。
如果 USB 裝置描述元中的版本、供應商 ID 或產品 ID 與預期值不符,配件就無法判斷裝置是否支援 Android 配件模式。配件應嘗試在配件模式下啟動裝置 (詳情請見下文),以判斷裝置是否支援。
重點: USB 配件必須在初始握手時傳送標頭。標頭包含製造商、型號和版本。雖然版本是選用欄位,但如果安裝的 Android 應用程式只符合版本,而配件未傳送版本,則搭載 Android 10 以下版本的 Android 裝置會因為系統程序中發生例外狀況而重新啟動。
嘗試在配件模式下啟動
如果版本、供應商和產品 ID 不對應至 Android 搭載裝置的配件模式,配件就無法判斷裝置是否支援配件模式 (但裝置並未處於配件模式),或是裝置不支援配件模式。發生這種情況的原因是,支援配件模式 (但未處於配件模式) 的裝置一開始會回報裝置製造商供應商和產品 ID,而不是 AOA 供應商和產品 ID。
配件應嘗試以配件模式啟動裝置,以判斷裝置是否支援該模式:
- 傳送 51 控制要求 (「Get Protocol」),判斷裝置是否支援 Android 配件通訊協定。如果裝置支援該通訊協定,則會傳回非零的數字,代表所支援的通訊協定版本。控制要求位於端點 0,具有下列特性:
requestType: USB_DIR_IN | USB_TYPE_VENDOR
request: 51
value: 0
index: 0
data: protocol version number (16 bits little endian sent from the
device to the accessory)
- 如果裝置傳回支援的通訊協定版本,請傳送控制要求,並附上識別字串資訊。裝置可利用這項資訊,判斷配件的適當應用程式 (如果沒有適當的應用程式,則會向使用者顯示網址)。控制項要求位於端點 0 (針對每個字串 ID),且具有下列特性:
requestType: USB_DIR_OUT | USB_TYPE_VENDOR
request: 52
value: 0
index: string ID
data zero terminated UTF8 string sent from accessory to device
系統支援下列字串 ID,每個字串的大小上限為 256 個位元組 (必須以 \0
結尾)。
manufacturer name: 0
model name: 1
description: 2
version: 3
URI: 4
serial number: 5
- 傳送控制要求,要求裝置以配件模式啟動。控制要求位於端點 0,具有下列特性:
requestType: USB_DIR_OUT | USB_TYPE_VENDOR
request: 53
value: 0
index: 0
data: none
完成這些步驟後,配件應等待已連結的 USB 裝置在配件模式下重新介紹自己,然後重新列舉已連結的裝置。如果裝置成功切換至配件模式,演算法會檢查供應商和產品 ID,藉此判斷是否支援配件模式,這些 ID 應為正確的值 (例如對應 Google 的供應商和產品 ID,而非裝置製造商的 ID)。如果 ID 和版本正確,配件就會開始與裝置建立通訊。
注意:AOA 目前不支援同時使用 AOA 和 MTP 連線。如要從 AOA 切換至 MTP,配件必須先斷開 USB 裝置 (以實體或電氣等效方式),然後再使用 MTP 重新連線。
如果任何步驟失敗,配件會判斷裝置不支援 Android 配件模式,並等待下一個裝置連線。
與裝置建立通訊
如果配件偵測到 Android 裝置處於配件模式,則可查詢裝置介面和端點描述符,取得用於與裝置通訊的大量端點。
介面和大量端點的數量取決於產品 ID。搭載 Android 的裝置,產品 ID 為:
0x2D00
有一個介面,其中包含兩個大量端點,用於輸入和輸出通訊。
0x2D01
有兩個介面,每個介面都有兩個大量端點,分別用於輸入和輸出通訊。第一個介面會處理標準通訊,第二個介面則會處理 ADB 通訊。如要使用介面,請找出第一個大量輸入和輸出端點,然後使用 SET_CONFIGURATION
(0x09
) 裝置要求,將裝置設定設為 1,再使用端點進行通訊。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Android Open Accessory 1.0\n\nAndroid USB accessories must adhere to the Android Open Accessory (AOA)\nprotocol, which defines how an accessory detects and sets up communication with\nan Android-powered device. Accessories should carry out the following steps:\n\n1. Wait for and detect a connected device.\n2. Determine the device's accessory mode support.\n3. Attempt to start the device in accessory mode (if needed).\n4. If the device supports AOA, establish communication with the device.\n\nThe following sections explain how to implement these steps.\n\nWait for and detect connected\ndevices\n-------------------------------------\n\nAccessories should continuously check for connected Android-powered devices.\nWhen a device is connected, the accessory should determine if the device\nsupports accessory mode.\n\nDetermine accessory mode support\n--------------------------------\n\n**Note:** USB debugging isn't required for connecting accessories but\nADB might be necessary during development. For details, see\n[Debug considerations](https://developer.android.com/guide/topics/connectivity/usb#debug-considerations).\n\nWhen an Android-powered device connects, it can be in one of three states:\n\n- Supports Android accessory mode and is already in accessory mode.\n- Supports Android accessory mode but it is not in accessory mode.\n- Does not support Android accessory mode.\n\nDuring the initial connection, the accessory should check the version, vendor ID,\nand product ID of the connected device's USB device descriptor. The vendor ID\nshould match Google's ID (`0x18D1`). If the device is already in\naccessory mode, the product ID should be `0x2D00` or\n`0x2D01` and the accessory can\n[establish communication with\nthe device](#establish-communication-with-the-device) through bulk transfer endpoints using its own communication\nprotocol (the device does not need to be started in accessory mode).\n\n**Note:** `0x2D00` is reserved for\nAndroid-powered devices that support accessory mode. `0x2D01` is\nreserved for devices that support accessory mode as well as the Android Debug\nBridge (ADB) protocol, which exposes a second interface with two bulk endpoints\nfor ADB. You can use these endpoints for debugging the accessory application if\nyou are simulating the accessory on a computer. In general, do not use this\ninterface unless the accessory implements a passthrough to ADB on the device.\n\nIf the version, vendor ID, or product ID in the USB device descriptor do not\nmatch expected values, the accessory cannot determine if the device supports\nAndroid accessory mode. The accessory should attempt to start the device in\naccessory mode (detailed below) to determine device support.\n\n**Key point:**A USB accessory must\nsend a header upon initial handshake. The header contains the manufacturer, model, and\nversion. Though version is an optional field, if an Android app is installed that only\nmatches on version, but the accessory doesn't send a version, Android devices\nrunning on Android 10 and below will reboot due to an exception being thrown in\nthe system process.\n\nAttempt to start in accessory\nmode\n----------------------------------\n\nIf the version, vendor, and product IDs do not correspond to an Android-powered\ndevice in accessory mode, the accessory cannot determine if the device supports (but\nis not in) accessory mode or if the device does not support accessory mode. This\ncan occur because devices that support accessory mode (but are not in accessory\nmode) initially report the *device* manufacturer vendor and product IDs\ninstead of the *AOA* vendor and product IDs.\n\nThe accessory should try to start the device in accessory mode to determine\nif the device supports that mode:\n\n1. Send a 51 control request (\"Get Protocol\") to determine if the device supports the Android accessory protocol. If the device supports the protocol, it returns a non-zero number that represents the supported protocol version. The control request is on endpoint 0 with the following characteristics: \n\n ```\n requestType: USB_DIR_IN | USB_TYPE_VENDOR\n request: 51\n value: 0\n index: 0\n data: protocol version number (16 bits little endian sent from the\n device to the accessory)\n ```\n2. If the device returns a supported protocol version, send a control request with identifying string information to the device. This information allows the device to determine an appropriate application for the accessory (or present a URL to the user if an appropriate application does not exist). The control request is on endpoint 0 (for each string ID) with the following characteristics: \n\n ```\n requestType: USB_DIR_OUT | USB_TYPE_VENDOR\n request: 52\n value: 0\n index: string ID\n data zero terminated UTF8 string sent from accessory to device\n ```\n\n The following string IDs are supported, with a maximum size of 256 bytes\n for each string (must be zero-terminated with `\\0`). \n\n ```\n manufacturer name: 0\n model name: 1\n description: 2\n version: 3\n URI: 4\n serial number: 5\n ```\n3. Send a control request to ask the device to start in accessory mode. The control request is on endpoint 0 with the following characteristics: \n\n ```\n requestType: USB_DIR_OUT | USB_TYPE_VENDOR\n request: 53\n value: 0\n index: 0\n data: none\n ```\n\nAfter completing these steps, the accessory should wait for the connected USB\ndevice to re-introduce itself on the bus in accessory mode, then re-enumerate\nconnected devices. The algorithm\n[determines accessory mode support](#determine-accessory-mode-support)\nby checking the vendor and product IDs, which should be correct (for example, correspond\nto Google's vendor and product IDs instead of to the device manufacturer's IDs) if\nthe device successfully switched to accessory mode. If IDs and version are correct,\nthe accessory moves to [establish\ncommunication with the device](#establish-communication-with-the-device).\n\n**Note:** AOA does not currently support\nsimultaneous AOA and MTP connections. To switch from AOA to MTP, the accessory\nmust first disconnect the USB device (either physically or in an electrically\nequivalent way) and then reconnect using MTP.\n\nIf any step fails, the accessory determines the device does not support\nAndroid accessory mode and waits for the next device to connect.\n\nEstablish communication with\nthe device\n---------------------------------------\n\nIf the accessory detects an Android-powered device in accessory mode, the\naccessory can query the device interface and endpoint descriptors to obtain the\nbulk endpoints for communicating with the device.\n\nThe number of interfaces and bulk endpoints depends on the product ID. An\nAndroid-powered device with a product ID of:\n\n- `0x2D00` has one interface with two bulk endpoints for input and output communication.\n- `0x2D01` has two interfaces with two bulk endpoints each for input and output communication. The first interface handles standard communication and the second interface handles ADB communication. To use an interface, locate the first bulk input and output endpoints, set the device configuration to a value of 1 with a `SET_CONFIGURATION` (`0x09`) device request, then communicate using the endpoints."]]