USB-Zubehör – Übersicht

Ü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 die android.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 Funktion android.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 die android.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 einem NullPointerException 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:

  1. 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.
  2. Bitten Sie den Nutzer um die Berechtigung zur Kommunikation mit dem Zubehör, falls noch nicht geschehen erhalten haben.
  3. 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.