Pourquoi un lecteur atteint-il une autre application que la vôtre ?
Parce qu'un autre service a enregistré le même identifiant, et qu'Android tranche le conflit avant que votre code ne s'exécute : l'application de portefeuille par défaut l'emporte, puis le service unique enregistré, et sinon l'utilisateur est interrogé. Une activité au premier plan peut renverser le résultat par setPreferredService.
La table d'acheminement décide en premier
Le contrôleur NFC détient une table d'acheminement : une liste finie de règles, chacune appariant un identifiant à une destination, le processeur hôte où tournent les applications ou un élément sécurisé raccordé. Quand un lecteur envoie un SELECT, le contrôleur apparie l'identifiant et envoie cette commande et toutes les suivantes à cette destination, jusqu'à ce qu'un autre SELECT arrive ou que la liaison se rompe. Le guide de l'émulation de carte d'Android décrit la table et précise que les applications ne la configurent jamais ; la plateforme la bâtit à partir des services installés et de ce que l'utilisateur a choisi.
Deux conséquences en découlent. Les appariements partiels, qu'ISO/IEC 7816-4 autorise, ne sont pas pris en charge par l'émulation de carte par l'hôte d'Android, donc un identifiant s'apparie en entier ou pas du tout. Et la table a une taille, même si le guide exige des appareils qu'ils acheminent vers l'hôte les identifiants que votre application a enregistrés.
Comment Android tranche un conflit
Plusieurs services peuvent enregistrer le même identifiant, et le guide donne l'ordre. L'application de portefeuille par défaut l'emporte si elle a enregistré l'identifiant. À défaut, le service unique qui l'a enregistré est invoqué. Si plusieurs l'ont fait, Android demande à l'utilisateur lequel employer.
La catégorie paiement resserre encore. Un seul groupe de paiement est actif sur l'appareil à la fois, et une application qui enregistre des identifiants de paiement ne transige qu'en tant que détentrice du rôle de portefeuille, depuis Android 15, ou depuis le premier plan. Un schéma qui fonctionne chez un seul commerçant appartient à l'autre catégorie, dont les groupes peuvent rester actifs en permanence et qui ne se dispute pas cette place unique.
Une application peut demander le rôle plutôt que l'espérer : RoleManager.ROLE_WALLET avec createRequestRoleIntent, et isRoleHeld pour savoir où elle en est.
Ce que change une activité au premier plan
setPreferredService nomme le service à préférer tant qu'une activité est reprise, et elle renverse la résolution ci-dessus. La référence de CardEmulation la demande dans onResume et demande unsetPreferredService dans onPause, le système ne conservant pas la préférence : elle doit être reposée à chaque reprise de l'activité.
L'appel échoue dans deux cas, tous deux liés au paiement. Si le service enregistre des identifiants de paiement et que l'utilisateur n'autorise pas les applications de premier plan à renverser le service de paiement par défaut. Et s'il enregistre dans l'autre catégorie des identifiants que le service de paiement par défaut traite aussi, sous le même choix de l'utilisateur. categoryAllowsForegroundPreference répond avant l'essai.
Que vérifier quand un contact part ailleurs
Demandez à la plateforme ce qu'elle en pense. isDefaultServiceForCategory répond pour une catégorie, mais la référence avertit qu'elle rend toujours faux quand le mode de sélection est de toujours demander ou de demander en cas de conflit ; dans ces modes, isDefaultServiceForAid est la question qui a du sens. getSelectionModeForCategory vous dit dans quel mode vous êtes.
Regardez ensuite hors de votre application. Une autre application installée peut enregistrer le même identifiant, et un service hors hôte peut le réclamer pour un élément sécurisé, auquel cas l'échange n'atteint jamais le moindre code hôte. Lire les identifiants que votre service a enregistrés, et les comparer à ce que le lecteur sélectionne, règle la plupart de ces cas plus vite que d'y raisonner : la page des APDU couvre le SELECT lui-même.
Questions fréquentes
Qui l'emporte quand deux applications enregistrent le même identifiant ?
L'application de portefeuille par défaut, si elle l'a enregistré. Sinon le service unique qui l'a fait, et si plusieurs l'ont fait, Android demande à l'utilisateur.
Pourquoi setPreferredService rend-elle faux ?
Le service enregistre des identifiants de paiement, ou des identifiants que le service de paiement par défaut traite aussi, et l'utilisateur n'a pas autorisé le premier plan à renverser ce service.
Android apparie-t-il une partie d'un identifiant ?
Non. Les appariements partiels existent dans ISO/IEC 7816-4 mais l'émulation de carte par l'hôte d'Android ne les prend pas en charge.
Comment une application devient-elle le portefeuille par défaut ?
En demandant le rôle de portefeuille par RoleManager.createRequestRoleIntent, et en vérifiant par isRoleHeld. C'est l'utilisateur qui l'accorde.