Aller au contenu
Langue : FR

Comment une application Android émule-t-elle une carte par l'hôte ?

Avec un service qui étend HostApduService et répond aux APDU, déclaré au manifeste avec le filtre d'Intent de l'émulation de carte, la permission BIND_NFC_SERVICE et un fichier XML qui enregistre ses identifiants d'application dans une catégorie. Android démarre le service au contact, même application fermée.

Le service et ses deux méthodes

L'émulation vit dans un service, pas dans une activité. Le guide de l'émulation de carte d'Android bâtit le mécanisme sur HostApduService, qui s'exécute en arrière plan : un contact le démarre s'il ne tourne pas, et la transaction a lieu sans que l'application soit ouverte. Vérifiez FEATURE_NFC_HOST_CARD_EMULATION avant de compter dessus, et déclarez-la par uses-feature au manifeste.

La classe a deux méthodes à implémenter. processCommandApdu() est appelée pour chaque APDU que le lecteur envoie, et rend les octets de la réponse. Elle s'exécute sur le fil principal, donc une réponse qui demande du travail rend null et arrive plus tard par sendResponseApdu() depuis un autre fil. onDeactivated() est appelée quand le lecteur sélectionne un identifiant qui mène à un autre service, ou quand la liaison radio se rompt, et son argument dit lequel des deux s'est produit.

Ce qui circule est un APDU, comme le décrit la page des APDU. Android émule l'ISO-DEP, ISO/IEC 14443-4, et traite les commandes d'ISO/IEC 7816-4 ; le guide impose l'ISO-DEP sur NFC-A et laisse NFC-B facultatif. L'échange se fait à tour de rôle et Android ne gère qu'un seul canal logique, donc commandes et réponses alternent une à une.

Ce que déclarent le manifeste et le XML

La déclaration du service porte trois ajouts : un filtre d'Intent pour l'action du service APDU hôte, la permission android.permission.BIND_NFC_SERVICE avec android:exported à vrai, et une balise de meta data qui pointe vers une ressource XML. La permission est une permission système, donc l'exiger revient à n'autoriser que le système d'exploitation à se lier au service. L'application détient aussi la permission NFC.

Le fichier XML est là où vivent les identifiants. Sa racine, host-apdu-service, porte une description destinée à l'utilisateur et, facultativement, requireDeviceUnlock. Elle contient une ou plusieurs balises aid-group, chacune avec sa description, une catégorie, et une ou plusieurs balises aid-filter portant un seul identifiant chacune, écrit en hexadécimal avec un nombre pair de caractères.

Un service qui répond depuis un élément sécurisé plutôt que depuis votre code se déclare de la même façon, avec l'action hors hôte et une racine offhost-apdu-service. Android n'offre aucune API pour parler directement à un élément sécurisé, ce que la page de l'élément sécurisé replace dans son contexte.

Groupes d'identifiants et catégories

Un identifiant d'application fait jusqu'à seize octets, et le lecteur le nomme dans une commande SELECT. Le guide recommande d'enregistrer le vôtre auprès d'ISO/IEC 7816-5 quand vous déployez vos propres lecteurs, pour qu'il n'entre en collision avec personne. Les identifiants qui vont ensemble tiennent dans un même groupe, et Android achemine un groupe d'un bloc : ou bien tous ses identifiants atteignent votre service, ou bien aucun.

Chaque groupe déclare une catégorie, paiement ou autre. Un seul groupe de paiement peut être actif sur l'appareil à la fois, et une application qui enregistre des identifiants de paiement ne transige que si elle détient le rôle de portefeuille, depuis Android 15, ou si elle est au premier plan et a appelé setPreferredService. Un schéma en boucle fermée, utilisable chez un seul commerçant, appartient à l'autre catégorie, où les groupes peuvent rester actifs en permanence. Quel service un lecteur atteint réellement est le sujet de la page de l'acheminement.

Ce que l'échange doit respecter

Restez court. Le guide fixe une borne haute raisonnable autour de 1 Ko de données, échangeables en quelque 300 ms, et ce budget décide du temps pendant lequel l'utilisateur doit tenir le téléphone contre le lecteur.

Restez dans ce que la plateforme émule. L'émulation de carte par l'hôte répond à l'échange de commandes standard ; un schéma dont la sécurité se situe sous cette couche, MIFARE Classic en tête, ne peut pas être émulé, comme l'explique aux lecteurs qui n'écrivent pas le code la page de l'émulation de carte par l'hôte.

Et décidez tôt de ce qui se passe écran éteint ou téléphone verrouillé, parce que la réponse dépend de la version d'Android et d'un réglage de l'appareil plutôt que de votre seul code. La page de l'écran éteint la prend version par version.

Questions fréquentes

L'application doit-elle être ouverte pour que l'émulation fonctionne ?

Non. Un contact démarre le service s'il ne tourne pas déjà, et l'échange a lieu en arrière plan sans aucun écran de votre part.

L'émulation de carte par l'hôte peut-elle émuler une carte MIFARE Classic ?

Non. Android émule l'ISO-DEP et traite les commandes d'ISO/IEC 7816-4, et les schémas dont la sécurité se situe sous cette couche sont hors de portée.

Pourquoi processCommandApdu est-elle appelée sur le fil principal ?

Parce que le lecteur attend une réponse. Rendez null quand la réponse demande du travail, puis envoyez-la par sendResponseApdu depuis un autre fil.

Que signifie onDeactivated ?

Soit le lecteur a sélectionné un identifiant qui mène à un autre service, soit la liaison radio s'est rompue. L'argument dit lequel des deux.