Über den USB-Zubehörmodus können Nutzer Speziell für Android-Geräte entwickelte USB-Host-Hardware Das Zubehör muss den an das Android-Zubehörprotokoll, das in der Dokumentation zum Android Accessory Development Kit beschrieben wird. Dadurch können Android-Geräte, die nicht als USB-Host fungieren können, dennoch mit USB interagieren. Hardware. Wenn sich ein Android-Gerät im USB-Zubehörmodus befindet, wird der angeschlossene fungiert als Host, versorgt den USB-Bus mit Strom und listet die verbundenen Geräte auf. Android 3.1 (API-Level 12) unterstützt den USB-Zubehörmodus und die Funktion wird auch zu Android 2.3.4 (API-Level 10) zur Unterstützung einer breiteren Palette von Geräten.
Die richtigen APIs für USB-Zubehör auswählen
Obwohl die APIs für USB-Zubehör in Android 3.1 eingeführt wurden, sind sie auch unter Android 2.3.4 mit der Google APIs-Add-on-Bibliothek verfügbar. Da diese APIs mithilfe einer externen Bibliothek zurückportiert wird, gibt es zwei Pakete, die Sie importieren können, Zubehörmodus. Je nachdem, welche Android-Geräte Sie unterstützen möchten, verwenden Sie eines anstelle des anderen:
com.android.future.usb
: Zur Unterstützung des USB-Zubehörmodus in Android 2.3.4 muss die Google APIs-Add-on Bibliothek enthält die rückportierten USB-Zubehör-APIs, die in dieser -Namespace auf sie zugegriffen werden. Android 3.1 unterstützt auch das Importieren und Aufrufen der Klassen innerhalb dieses Namespace, um unterstützen Anwendungen, die mit der Add-on-Bibliothek geschrieben wurden. Diese Add-on-Bibliothek ist ein Thin Wrapper um dieandroid.hardware.usb
-Zubehör-APIs zu ergänzen und unterstützt den USB-Hostmodus nicht. Wenn Wenn Sie eine möglichst große Auswahl an Geräten unterstützen möchten, die den USB-Zubehörmodus unterstützen, verwenden Sie das Add-on. und importieren dieses Paket. Beachten Sie, dass nicht alle Geräte mit Android 2.3.4 erforderlich, um das USB-Zubehör zu unterstützen. Jeder Gerätehersteller entscheidet darüber, ob diese Funktion unterstützt wird oder nicht. Deshalb musst du sie in deinem Manifest deklarieren. -Datei.android.hardware.usb
: Dieser Namespace enthält die Klassen, die USB unterstützen. Zubehörmodus in Android 3.1. Dieses Paket ist Teil der Framework-APIs, Android 3.1 unterstützt den USB-Zubehörmodus ohne die Verwendung einer Add-on-Bibliothek. Dieses Paket verwenden wenn Sie nur Geräte mit Android 3.1 oder höher benötigen, die USB-Verbindungen unterstützen. Zubehörmodus, den Sie in Ihrer Manifestdatei deklarieren können.
Add-on-Bibliothek für Google APIs installieren
Wenn Sie das Add-on installieren möchten, können Sie die Google APIs Android API 10 installieren. mit dem SDK Manager. Siehe Google APIs installieren Add-on.
API-Übersicht
Da die Add-on-Bibliothek ein Wrapper für die Framework-APIs ist, werden die Klassen, die die
USB-Zubehör funktioniert ähnlich. Sie können die Referenzdokumentation für die android.hardware.usb
auch dann verwenden, wenn Sie die Add-on-Bibliothek verwenden.
Hinweis: Die Verwendung der Funktion wird nur geringfügig verwendet. Unterschied zwischen der Add-on-Bibliothek und den Framework-APIs, die Sie kennen sollten.
In der folgenden Tabelle werden die Klassen beschrieben, die die APIs für USB-Zubehör unterstützen:
Klasse | Beschreibung |
---|---|
UsbManager |
Ermöglicht die Auflistung und Kommunikation von angeschlossenem USB-Zubehör. |
UsbAccessory |
Stellt ein USB-Zubehör dar und enthält Methoden für den Zugriff auf seine identifizierende Kennung Informationen. |
Nutzungsunterschiede zwischen der Add-on-Bibliothek und den Plattform-APIs
Es gibt zwei Nutzungsunterschiede zwischen der Verwendung der Google APIs-Add-on-Bibliothek und der Plattform APIs
Wenn Sie die Add-on-Bibliothek verwenden, müssen Sie das UsbManager
-Objekt so abrufen:
Kotlin
val manager = UsbManager.getInstance(this)
Java
UsbManager manager = UsbManager.getInstance(this);
Wenn Sie die Add-on-Bibliothek nicht verwenden, müssen Sie das UsbManager
-Objekt so abrufen:
Kotlin
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
Java
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Wenn Sie nach einem verbundenen Zubehör mit einem Intent-Filter filtern, ist das Objekt UsbAccessory
im Intent enthalten, der an Ihren
. Wenn Sie die Add-on-Bibliothek verwenden, müssen Sie das UsbAccessory
-Objekt so abrufen:
Kotlin
val accessory = UsbManager.getAccessory(intent)
Java
UsbAccessory accessory = UsbManager.getAccessory(intent);
Wenn Sie die Add-on-Bibliothek nicht verwenden, müssen Sie das UsbAccessory
-Objekt so abrufen:
Kotlin
val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory
Java
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
Anforderungen an Android-Manifest
In der folgenden Liste wird beschrieben, was Sie der Manifestdatei Ihrer Anwendung hinzufügen müssen, bevor Sie mit den APIs für USB-Zubehör. Die Manifest- und Ressourcendatei Beispiele zeigen, wie diese Elemente deklariert werden:
- Da nicht alle Android-Geräte die APIs für USB-Zubehör unterstützen,
Ein
<uses-feature>
-Element enthalten, das deklariert, dass deine App die Funktionandroid.hardware.usb.accessory
. - Wenn Sie den
Add-on-Bibliothek,
fügen Sie das Element
<uses-library>
hinzu,com.android.future.usb.accessory
für die Bibliothek. - Wenn Sie die Add-on-Bibliothek verwenden, legen Sie als SDK-Mindestwert der Anwendung API-Level 10 fest
oder 12, wenn Sie das Paket
android.hardware.usb
verwenden. -
Wenn Sie möchten, dass Ihre App über angeschlossenes USB-Zubehör benachrichtigt wird, geben Sie eine
<intent-filter>
- und<meta-data>
-Element-Paar für dieandroid.hardware.usb.action.USB_ACCESSORY_ATTACHED
Intent in deiner Hauptaktivität. Das<meta-data>
-Element verweist auf eine externe XML-Ressourcendatei, die deklariert Identifizierungsinformationen für das Zubehörteil, das Sie erkennen möchten.Deklarieren Sie in der XML-Ressourcendatei
<usb-accessory>
-Elemente für die die Sie filtern möchten. Jeder<usb-accessory>
kann die folgende Attribute:manufacturer
model
version
Es wird nicht empfohlen, nach
version
zu filtern. Zubehör oder Gerät geben nicht immer einen Versionsstring an (absichtlich oder unbeabsichtigt). Wenn in Ihrer App ein Versionsattribut deklariert ist, nach dem gefiltert werden soll, und das Zubehör oder Gerät gibt keinen Versionsstring an. Dies führt zu einemNullPointerException
bei früheren Android-Versionen. Dieses Problem wurde in Android 12 behoben.Speichern Sie die Ressourcendatei im Verzeichnis
res/xml/
. Der Name der Ressourcendatei (ohne die Erweiterung „.xml“) muss mit der Datei übereinstimmen, die Sie in den<meta-data>
-Element. Das Format für die XML-Ressourcendatei wird auch unter im Beispiel unten.
Beispiele für Manifest- und Ressourcendateien
Das folgende Beispiel zeigt ein Beispielmanifest und die zugehörige Ressourcendatei:
<manifest ...> <uses-feature android:name="android.hardware.usb.accessory" /> <uses-sdk android:minSdkVersion="<version>" /> ... <application> <uses-library android:name="com.android.future.usb.accessory" /> <activity ...> ... <intent-filter> <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/accessory_filter" /> </activity> </application> </manifest>
In diesem Fall sollte die folgende Ressourcendatei
res/xml/accessory_filter.xml
und gibt an, dass jedes Zubehör, das die
Modell, Hersteller und Version gefiltert werden sollen. Das Zubehör sendet diese
weist dem Android-Gerät Folgendes zu:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/> </resources>
Mit Zubehör arbeiten
Wenn Nutzer USB-Zubehör an ein Android-Gerät anschließen, kann das Android-System ermitteln, ob Ihre Anwendung an dem verbundenen Zubehör interessiert ist. In diesem Fall können Sie gegebenenfalls mit dem Zubehör kommunizieren. Dazu muss Ihre Anwendung folgende Voraussetzungen erfüllen:
- Mit einem Intent-Filter, der nach Zubehör filtert, kannst du verbundenes Zubehör entdecken verbundenen Ereignissen oder durch Auflisten verbundener Zubehörteile und Auswahl des passenden Zubehörs.
- Bitten Sie den Nutzer um die Berechtigung zur Kommunikation mit dem Zubehör, falls noch nicht geschehen erhalten haben.
- Durch Lesen und Schreiben von Daten auf der entsprechenden Benutzeroberfläche mit dem Zubehör kommunizieren Endpunkten.
Zubehör entdecken
Deine App kann Zubehör finden, indem sie entweder einen Intent-Filter verwendet, um benachrichtigt zu werden, der Nutzer ein Zubehör verbindet oder Zubehör aufzählt, das bereits verbunden ist. Bei Verwendung eines Intent-Filter ist nützlich, wenn Sie möchten, dass Ihre Anwendung automatisch ein gewünschtes Zubehörteil. Die Auflistung aller verbundenen Zubehörteile ist nützlich, verbundenes Zubehör oder wenn deine App nicht nach einem Intent gefiltert hat.
Intent-Filter verwenden
Damit Ihre App ein bestimmtes USB-Zubehör erkennt, können Sie einen Intent-Filter angeben.
um nach dem Intent android.hardware.usb.action.USB_ACCESSORY_ATTACHED
zu filtern. Entlang
müssen Sie bei diesem Intent-Filter
eine Ressourcendatei mit den Eigenschaften
Zubehörteils wie Hersteller, Modell und Version.
Das folgende Beispiel zeigt, wie der Intent-Filter deklariert wird:
<activity ...> ... <intent-filter> <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/accessory_filter" /> </activity>
Das folgende Beispiel zeigt, wie die entsprechende Ressourcendatei deklariert wird, die die USB-Zubehör, das Sie interessiert:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" /> </resources>
In Ihrer Aktivität können Sie die UsbAccessory
abrufen, die für
das angehängte Zubehör aus dem Intent (mit der Add-on-Bibliothek):
Kotlin
val accessory = UsbManager.getAccessory(intent)
Java
UsbAccessory accessory = UsbManager.getAccessory(intent);
oder so (mit den Plattform-APIs):
Kotlin
val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory
Java
UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
Zubehör auflisten
Sie können in Ihrer Anwendung Zubehör auflisten, das während der Anwendung ausgeführt wird.
Methode getAccessoryList()
verwenden
um ein Array für alle angeschlossenen USB-Zubehörteile zu erhalten:
Kotlin
val manager = getSystemService(Context.USB_SERVICE) as UsbManager val accessoryList: Array<out UsbAccessory> = manager.accessoryList
Java
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); UsbAccessory[] accessoryList = manager.getAccessoryList();
Hinweis: Unter zu einer bestimmten Zeit.
Erlaubnis zur Kommunikation mit einem Zubehör einholen
Bevor Sie mit dem USB-Zubehör kommunizieren können, muss Ihre App über die Berechtigung Ihres Nutzenden.
Hinweis: Wenn Ihre Anwendung einen Intent-Filter, um Zubehör zu entdecken, während sie verbunden sind, erhält der Nutzer automatisch Berechtigung, wenn der Nutzer der Anwendung erlaubt, den Intent zu verarbeiten. Falls nicht, müssen Sie ausdrücklich in Ihrer App bestätigen, bevor Sie eine Verbindung zum Zubehör herstellen.
In einigen Situationen kann es notwendig sein, ausdrücklich um Erlaubnis zu bitten, z. B. wenn deine zeigt die Anwendung Zubehör an, die bereits verbunden ist und mit eins. Sie müssen Ihre Berechtigung für den Zugriff auf das Zubehör prüfen, bevor Sie versuchen, mit ihm zu kommunizieren. Andernfalls erhalten Sie einen Laufzeitfehler, wenn der Nutzer die Zugriffsberechtigung für die Zubehörteils.
Erstellen Sie zuerst einen Übertragungsempfänger, um die Berechtigung explizit einzuholen. Dieser Empfänger wartet auf
Intent, der beim Aufrufen von requestPermission()
übertragen wird. Beim Aufruf von requestPermission()
wird ein Dialogfeld für die
Nutzer bittet um Erlaubnis, eine Verbindung zum Zubehör herzustellen. Der folgende Beispielcode zeigt, wie Sie
den Übertragungsempfänger erstellen:
Kotlin
private const val ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION" private val usbReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (ACTION_USB_PERMISSION == intent.action) { synchronized(this) { val accessory: UsbAccessory? = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { accessory?.apply { // call method to set up accessory communication } } else { Log.d(TAG, "permission denied for accessory $accessory") } } } } }
Java
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private final BroadcastReceiver usbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if(accessory != null){ // call method to set up accessory communication } } else { Log.d(TAG, "permission denied for accessory " + accessory); } } } } };
Registrieren Sie den Übertragungsempfänger über die onCreate()
-Methode in Ihrem
Aktivität:
Kotlin
private const val ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION" ... val manager = getSystemService(Context.USB_SERVICE) as UsbManager ... permissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0) val filter = IntentFilter(ACTION_USB_PERMISSION) registerReceiver(usbReceiver, filter)
Java
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; ... permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(usbReceiver, filter);
Rufe die Funktion
requestPermission()
-Methode:
Kotlin
lateinit var accessory: UsbAccessory ... usbManager.requestPermission(accessory, permissionIntent)
Java
UsbAccessory accessory; ... usbManager.requestPermission(accessory, permissionIntent);
Wenn Nutzer auf das Dialogfeld antworten, empfängt der Übertragungsempfänger den Intent mit dem Ereignis
EXTRA_PERMISSION_GRANTED
-Extra, ein boolescher Wert
die die Antwort darstellt. Überprüfen Sie diese Zusatzinformationen auf den Wert "true", bevor Sie eine Verbindung zum
Zubehörteils.
Mit Zubehör kommunizieren
Sie können über die UsbManager
mit dem Zubehör kommunizieren,
Rufen Sie einen Dateideskriptor ab, mit dem Sie Ein- und Ausgabestreams zum Lesen und Schreiben von Daten einrichten können
Beschreibung. Die Streams stellen die Bulk-Endpunkte für die Ein- und Ausgabe des Zubehörs dar. Sie sollten
die Kommunikation zwischen Gerät und Zubehör über einen anderen Faden unterbrechen, damit Sie das Gerät nicht sperren.
UI-Hauptthread. Das folgende Beispiel zeigt, wie ein Zubehör geöffnet wird, um mit ihm zu kommunizieren:
Kotlin
private lateinit var accessory: UsbAccessory private var fileDescriptor: ParcelFileDescriptor? = null private var inputStream: FileInputStream? = null private var outputStream: FileOutputStream? = null ... private fun openAccessory() { Log.d(TAG, "openAccessory: $mAccessory") fileDescriptor = usbManager.openAccessory(accessory) fileDescriptor?.fileDescriptor?.also { fd -> inputStream = FileInputStream(fd) outputStream = FileOutputStream(fd) val thread = Thread(null, this, "AccessoryThread") thread.start() } }
Java
UsbAccessory accessory; ParcelFileDescriptor fileDescriptor; FileInputStream inputStream; FileOutputStream outputStream; ... private void openAccessory() { Log.d(TAG, "openAccessory: " + accessory); fileDescriptor = usbManager.openAccessory(accessory); if (fileDescriptor != null) { FileDescriptor fd = fileDescriptor.getFileDescriptor(); inputStream = new FileInputStream(fd); outputStream = new FileOutputStream(fd); Thread thread = new Thread(null, this, "AccessoryThread"); thread.start(); } }
Mit der Methode run()
des Threads können Sie mit dem folgenden Befehl auf das Zubehör schreiben und lesen.
FileInputStream
- oder FileOutputStream
-Objekt Beim Lesen
von einem Zubehörteil mit einem FileInputStream
-Objekt abzurufen,
groß genug ist, um die USB-Paketdaten zu speichern. Das Protokoll für Android-Zubehör unterstützt
hat das Paket bis zu 16.384 Byte im Zwischenspeicher. Ihr könnt den Puffer also immer als Puffer angeben.
der Einfachheit halber die Größe.
Hinweis:Auf einer niedrigeren Ebene haben die Pakete für den USB-Speicher Full-Speed-Zubehör und 512 Byte für USB-Highspeed-Zubehör. Android-Zubehör -Protokoll bündelt die Pakete für beide Geschwindigkeiten der Einfachheit halber in einem logischen Paket.
Weitere Informationen zur Verwendung von Threads in Android finden Sie unter Prozesse und Threads:
Kommunikation mit einem Zubehör beenden
Wenn Sie die Kommunikation mit einem Zubehör abgeschlossen haben oder das Zubehörprodukt getrennt wurde, schließen Sie das
Dateideskriptor, die Sie durch Aufrufen von close()
geöffnet haben.
Um auf getrennte Ereignisse zu warten, erstellen Sie wie unten einen Broadcast-Empfänger:
Kotlin
var usbReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (UsbManager.ACTION_USB_ACCESSORY_DETACHED == intent.action) { val accessory: UsbAccessory? = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) accessory?.apply { // call your method that cleans up and closes communication with the accessory } } } }
Java
BroadcastReceiver usbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) { UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); if (accessory != null) { // call your method that cleans up and closes communication with the accessory } } } };
Wenn Sie den Übertragungsempfänger in der Anwendung und nicht im Manifest erstellen, können Sie -Anwendung so ab, dass getrennte Ereignisse nur während ihrer Ausführung verarbeitet werden. So werden getrennte Ereignisse wird nur an die aktuell ausgeführte Anwendung gesendet und nicht an alle Anwendungen gesendet.