Le mode accessoire USB permet aux utilisateurs de se connecter Matériel hôte USB spécialement conçu pour les appareils Android Les accessoires doivent adhérer au protocole d'accessoire Android décrit dans la documentation sur le kit de développement d'accessoires Android. Cela permet aux appareils Android qui ne peuvent pas servir d'hôte USB de continuer à interagir avec l'USB matériel. Lorsqu'un appareil Android est en mode accessoire USB, la clé USB Android connectée l'accessoire agit en tant qu'hôte, alimente le bus USB et énumère les appareils connectés. Android 3.1 (niveau d'API 12) prend en charge le mode accessoire USB et est également rétroporté vers Android 2.3.4 (niveau d'API 10) pour une compatibilité avec un plus grand nombre d'appareils.
Choisir les API d'accessoires USB appropriées
Bien que les API d'accessoires USB aient été introduites sur la plate-forme sous Android 3.1, elles le sont également disponible sur Android 2.3.4 via la bibliothèque de modules complémentaires des API Google. Ces API étant rétroporté à l'aide d'une bibliothèque externe, vous pouvez importer deux packages pour prendre en charge mode accessoire. Selon les appareils Android que vous souhaitez prendre en charge, vous devrez peut-être utilisez l'un plutôt que l'autre:
com.android.future.usb
: pour prendre en charge le mode accessoire USB sous Android 2.3.4, le paramètre Module complémentaire des API Google qui inclut les API d'accessoires USB rétroportées, qui sont contenues dans ce espace de noms. Android 3.1 permet également d'importer et d'appeler les classes de cet espace de noms pour prendre en charge les applications écrites avec la bibliothèque de modules complémentaires. Cette bibliothèque de modules complémentaires est un wrapper léger autour des API d'accessoiresandroid.hardware.usb
et n'est pas compatible avec le mode hôte USB. Si compatible avec le plus grand nombre d'appareils compatibles avec le mode accessoire USB, utilisez le module complémentaire bibliothèque et importer ce package. Il est important de noter que les appareils équipés d'Android 2.3.4 ne sont pas tous requis pour prendre en charge la fonctionnalité d'accessoire USB. Chaque fabricant d'appareil décide accepter ou non cette fonctionnalité, c'est pourquoi vous devez la déclarer dans votre fichier manifeste ; .android.hardware.usb
: cet espace de noms contient les classes compatibles USB le mode accessoire sur Android 3.1. Ce package est inclus dans les API du framework : Android 3.1 prend en charge le mode accessoire USB sans bibliothèque de modules complémentaires. Utiliser ce package Si vous ne vous intéressez qu'aux appareils équipés d'Android 3.1 (ou version ultérieure) compatibles USB que vous pouvez déclarer dans votre fichier manifeste.
Installer la bibliothèque de modules complémentaires des API Google
Si vous souhaitez installer le module complémentaire, vous pouvez le faire en installant les API Google pour Android API 10 avec SDK Manager. Reportez-vous à la section Installation des API Google Module complémentaire pour en savoir plus sur l'installation de la bibliothèque de modules complémentaires.
Présentation de l'API
La bibliothèque de modules complémentaires étant un wrapper pour les API du framework, les classes compatibles avec le
Les fonctionnalités de l'accessoire USB sont similaires. Vous pouvez utiliser la documentation de référence sur android.hardware.usb
même si vous utilisez la bibliothèque de modules complémentaires.
Remarque:Cependant, une utilisation mineure entre la bibliothèque de modules complémentaires et les API de framework.
Le tableau suivant décrit les classes compatibles avec les API d'accessoires USB:
Classe | Description |
---|---|
UsbManager |
Permet d'énumérer les accessoires USB connectés et de communiquer avec eux. |
UsbAccessory |
Représente un accessoire USB et contient des méthodes pour accéder à son identifiant des informations. |
Différences d'utilisation entre la bibliothèque de modules complémentaires et les API de la plate-forme
Il existe deux différences d'utilisation entre la bibliothèque de modules complémentaires des API Google et la plate-forme. API.
Si vous utilisez la bibliothèque de modules complémentaires, vous devez obtenir l'objet UsbManager
de la manière suivante:
Kotlin
val manager = UsbManager.getInstance(this)
Java
UsbManager manager = UsbManager.getInstance(this);
Si vous n'utilisez pas la bibliothèque du module complémentaire, vous devez obtenir l'objet UsbManager
de la manière suivante:
Kotlin
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
Java
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Lorsque vous filtrez un accessoire connecté avec un filtre d'intent, l'objet UsbAccessory
est contenu dans l'intent transmis à votre
application. Si vous utilisez la bibliothèque de modules complémentaires, vous devez obtenir l'objet UsbAccessory
de la manière suivante:
Kotlin
val accessory = UsbManager.getAccessory(intent)
Java
UsbAccessory accessory = UsbManager.getAccessory(intent);
Si vous n'utilisez pas la bibliothèque du module complémentaire, vous devez obtenir l'objet UsbAccessory
de la manière suivante:
Kotlin
val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory
Java
UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
Exigences concernant les fichiers manifestes Android
La liste suivante décrit ce que vous devez ajouter au fichier manifeste de votre application avant avec les API d'accessoires USB. Le fichier manifeste et le fichier de ressources exemples montrent comment déclarer ces articles:
- La compatibilité avec les API d'accessoires USB n'est pas garantie pour tous les appareils Android.
incluent un élément
<uses-feature>
qui déclare que votre application utilise la fonctionnalitéandroid.hardware.usb.accessory
. - Si vous utilisez
bibliothèque de modules complémentaires
ajoutez l'élément
<uses-library>
en spécifiantcom.android.future.usb.accessory
pour la bibliothèque. - Définissez le SDK minimal de l'application sur le niveau d'API 10 si vous utilisez la bibliothèque de modules complémentaires.
ou 12 si vous utilisez le package
android.hardware.usb
. -
Si vous souhaitez que votre application soit informée lorsqu'un accessoire USB est connecté, spécifiez un Paire d'éléments
<intent-filter>
et<meta-data>
pour Intentandroid.hardware.usb.action.USB_ACCESSORY_ATTACHED
dans votre activité principale. L'élément<meta-data>
pointe vers un fichier de ressources XML externe qui déclare les informations permettant d'identifier l'accessoire que vous souhaitez détecter.Dans le fichier de ressources XML, déclarez les éléments
<usb-accessory>
pour accessoires que vous souhaitez filtrer. Chaque<usb-accessory>
peut avoir les attributs suivants:manufacturer
model
version
Le filtrage sur
version
n'est pas recommandé. Un accessoire ou que l'appareil ne spécifie pas toujours une chaîne de version (intentionnellement ou non). Lorsque votre application déclare un attribut de version à utiliser comme filtre et que l'accessoire ou l'appareil ne spécifie pas de chaîne de version, une erreurNullPointerException
est alors renvoyée sur versions antérieures d'Android. Ce problème est résolu dans Android 12.Enregistrez le fichier de ressources dans le répertoire
res/xml/
. Nom du fichier de ressources (sans l'extension .xml) doit être identique à celui spécifié dans le fichier Élément<meta-data>
. Le format du fichier de ressources XML est également indiqué dans l'exemple ci-dessous.
Exemples de fichiers manifestes et de ressources
Voici un exemple de fichier manifeste et le fichier de ressources correspondant:
<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>
Dans ce cas, le fichier de ressources suivant doit être enregistré dans
res/xml/accessory_filter.xml
, et indique que tout accessoire doté de la
le modèle, le fabricant et la version correspondants
doivent être filtrés. L'accessoire envoie ces
attribue l'appareil Android:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-accessory model="DemoKit" manufacturer="Google" version="1.0"/> </resources>
Utiliser des accessoires
Lorsque les utilisateurs connectent des accessoires USB à un appareil Android, le système Android peut déterminer si votre application est intéressée par l'accessoire connecté. Si c'est le cas, vous pouvez définir communiquer avec l'accessoire si vous le souhaitez. Pour ce faire, votre application doit:
- Découvrez les accessoires connectés à l'aide d'un filtre d'intent qui filtre les accessoires ou en énumérant les accessoires connectés et en trouvant celui qui convient.
- Demander à l'utilisateur l'autorisation de communiquer avec l'accessoire, si ce n'est pas déjà fait obtenues.
- Communiquer avec l'accessoire en lisant et en écrivant des données sur l'interface appropriée les points de terminaison.
Découvrir un accessoire
Votre application peut détecter des accessoires en utilisant un filtre d'intent pour être averti lorsque l’utilisateur connecte un accessoire ou en énumérant les accessoires qui sont déjà connectés. À l'aide d'un Le filtre d'intent est utile si vous voulez que votre application détecte automatiquement l'accessoire souhaité. L'énumération des accessoires connectés est utile si vous souhaitez obtenir la liste accessoires connectés ou si votre application n'a filtré aucun intent.
Utiliser un filtre d'intent
Pour que votre application détecte un accessoire USB spécifique, vous pouvez spécifier un filtre d'intent
pour filtrer l'intent android.hardware.usb.action.USB_ACCESSORY_ATTACHED
. Au-dessus
Avec ce filtre d'intent, vous devez spécifier un fichier de ressources spécifiant les propriétés de la clé USB
accessoire, tels que le fabricant, le modèle et la version.
L'exemple suivant montre comment déclarer le filtre d'intent:
<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>
L'exemple suivant montre comment déclarer le fichier de ressources correspondant qui spécifie le Les accessoires USB qui vous intéressent:
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-accessory manufacturer="Google, Inc." model="DemoKit" version="1.0" /> </resources>
Dans votre activité, vous pouvez obtenir le UsbAccessory
qui représente
l'accessoire associé de l'intent comme ceci (avec la bibliothèque de modules complémentaires):
Kotlin
val accessory = UsbManager.getAccessory(intent)
Java
UsbAccessory accessory = UsbManager.getAccessory(intent);
ou comme ceci (avec les API de la plate-forme):
Kotlin
val accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY) as UsbAccessory
Java
UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
Énumérer les accessoires
Vous pouvez demander à votre application d'énumérer les accessoires qui se sont identifiés l'application est en cours d'exécution.
Utiliser la méthode getAccessoryList()
pour obtenir un tableau de tous les accessoires USB connectés:
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();
Remarque : Un seul accessoire connecté est pris en charge dans à la fois.
Obtenir l'autorisation de communiquer avec un accessoire
Avant de pouvoir communiquer avec l'accessoire USB, votre application doit avoir l'autorisation de votre utilisateurs.
Remarque:Si votre application utilise un d'intention pour détecter les accessoires connectés, il reçoit automatiquement si l'utilisateur autorise votre application à gérer l'intent. Sinon, vous devez demander explicitement dans votre application avant de vous connecter à l'accessoire.
Il peut être nécessaire de demander explicitement l'autorisation dans certaines situations, par exemple lorsque votre énumère les accessoires qui sont déjà connectés et qui souhaitent communiquer avec 1. Vous devez vérifier si vous êtes autorisé à accéder à un accessoire avant d'essayer de communiquer avec lui. Si ce n'est pas le cas, vous recevrez une erreur d'exécution si l'utilisateur a refusé l'autorisation d'accéder à accessoire.
Pour obtenir explicitement l'autorisation, commencez par créer un broadcast receiver. Ce récepteur écoute
L'intent qui est diffusé lorsque vous appelez requestPermission()
. L'appel de requestPermission()
affiche une boîte de dialogue pour
utilisateur demandant l'autorisation de se connecter à l'accessoire. L'exemple de code suivant montre comment
créez le broadcast receiver:
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); } } } } };
Pour enregistrer le broadcast receiver, placez-le dans la méthode onCreate()
de votre
activité:
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);
Pour afficher la boîte de dialogue qui demande aux utilisateurs l'autorisation de se connecter à l'accessoire, appelez la méthode
Méthode requestPermission()
:
Kotlin
lateinit var accessory: UsbAccessory ... usbManager.requestPermission(accessory, permissionIntent)
Java
UsbAccessory accessory; ... usbManager.requestPermission(accessory, permissionIntent);
Lorsque les utilisateurs répondent à la boîte de dialogue, votre broadcast receiver reçoit l'intent qui contient le
EXTRA_PERMISSION_GRANTED
supplémentaire, qui est une valeur booléenne
représentant la réponse. Vérifiez dans cet extra la valeur "true" avant de vous connecter
accessoire.
Communiquer avec un accessoire
Vous pouvez communiquer avec l'accessoire en utilisant le UsbManager
pour
obtenir un descripteur de fichier dans lequel vous pouvez configurer des flux d'entrée et de sortie pour lire et écrire des données
du descripteur. Les flux représentent les points de terminaison groupés d'entrée et de sortie de l'accessoire. Vous devez définir
la communication entre l'appareil et l'accessoire dans un autre thread, afin de ne pas verrouiller
thread UI principal. L'exemple suivant montre comment ouvrir un accessoire pour communiquer avec:
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(); } }
Dans la méthode run()
du thread, vous pouvez lire et écrire sur l'accessoire en utilisant
les objets FileInputStream
ou FileOutputStream
. Pendant la lecture
d'un accessoire avec un objet FileInputStream
, assurez-vous que le tampon que
que vous utilisez est suffisamment volumineux
pour stocker les données des paquets USB. Le protocole d'accessoire Android est compatible avec
de paquets pouvant comporter jusqu'à 16 384 octets. Vous pouvez donc choisir de toujours déclarer votre tampon de cette
par souci de simplicité.
Remarque:À un niveau inférieur, la taille des paquets est de 64 octets pour les des accessoires pleine vitesse et 512 octets pour les accessoires USB haut débit. L'accessoire Android regroupe les paquets pour les deux vitesses en un seul paquet logique pour plus de simplicité.
Pour en savoir plus sur l'utilisation des threads sous Android, consultez la section Processus et Threads :
Mettre fin à la communication avec un accessoire
Lorsque vous avez terminé de communiquer avec un accessoire ou si celui-ci a été déconnecté, fermez l'appareil
descripteur de fichier que vous avez ouvert en appelant close()
.
Pour écouter les événements détachés, créez un broadcast receiver comme ci-dessous:
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 } } } };
La création du broadcast receiver dans l'application, et non du fichier manifeste, permet à une application pour ne gérer que les événements détachés pendant son exécution. De cette façon, les événements détachés envoyé uniquement à l'application en cours d'exécution et non diffusé à toutes les applications.