Mode lecteur ou dispatch au premier plan : lequel choisir sur Android ?
Le mode lecteur, pour un écran dont la raison d'être est de lire des tags. Il remet chaque tag à une fonction de rappel, peut sauter la vérification NDEF et le son du système, et suspend l'émulation de carte tant qu'il tourne. Le dispatch au premier plan convient à une application qui rencontre un tag de temps en temps et veut le recevoir comme le reste de ses entrées, sous forme d'Intent.
Ce que les deux font
Les deux donnent à l'activité affichée la priorité sur le prochain tag, avant toutes les applications qui se sont déclarées dans leur manifeste. La référence de NfcAdapter décrit le dispatch au premier plan comme une priorité donnée à l'activité affichée, et le mode lecteur comme une limitation du contrôleur tant que cette activité est au premier plan.
Aucun des deux ne survit à l'activité qui quitte l'écran. Le dispatch au premier plan doit être activé pendant que l'activité est reprise et désactivé avant la fin de son onPause, et l'appeler alors que l'activité n'est pas au premier plan lève IllegalStateException.
Et aucun des deux ne change ce qui se passe quand l'application est fermée. Un tag qui doit lancer l'application passe par le manifeste, ce que couvre la page du manifeste.
Ce que le mode lecteur change
Le mode lecteur fait du contrôleur un lecteur et rien d'autre. La référence indique qu'il désactive le pair à pair et l'émulation de carte tant qu'il tourne : un utilisateur qui ouvre votre écran de lecture à une caisse ne peut plus payer avec son téléphone tant qu'il n'en est pas sorti.
Il n'interroge que les technologies que vous nommez, par des drapeaux comme FLAG_READER_NFC_A ou FLAG_READER_NFC_V. Un écran fait pour des étiquettes ISO/IEC 15693 qui n'interroge que NFC-V ne réagit pas à une carte bancaire posée à côté.
FLAG_READER_SKIP_NDEF_CHECK empêche la plateforme de lire le tag à la recherche d'un message NDEF avant votre rappel. La référence en donne le coût sans détour : la classe Ndef n'est alors pas énumérée sur le tag, et le dispatch fondé sur NDEF ne fonctionne plus. C'est le drapeau d'un écran qui envoie ses propres commandes, et le mauvais drapeau pour un écran qui lit des messages.
FLAG_READER_NO_PLATFORM_SOUNDS coupe le son de détection du système, ce qui laisse à votre application la charge de dire à l'utilisateur qu'il s'est passé quelque chose. L'extra EXTRA_READER_PRESENCE_CHECK_DELAY fixe le délai que la plateforme emploie pour vérifier que le tag est toujours là.
Les tags arrivent par onTagDiscovered et non sous forme d'Intent. À partir du niveau d'API 37, le rappel dispose aussi de onTagLost, appelé quand le tag s'en va ; avant ce niveau, un départ se manifeste par une exception au prochain échange.
Pour lire un téléphone qui émule une carte par émulation de carte par l'hôte, la référence recommande FLAG_READER_NFC_A avec FLAG_READER_SKIP_NDEF_CHECK.
Ce que le dispatch garde
Le dispatch au premier plan change qui reçoit le tag et pas grand chose d'autre. La plateforme lit toujours le tag à la recherche d'un message NDEF et joue toujours son son de détection, le drapeau qui le coupe appartenant au mode lecteur, et rien dans la référence ne suspend l'émulation de carte pendant qu'il est actif.
Le tag arrive sous forme d'Intent, par le PendingIntent que vous fournissez. Le guide NFC avancé le construit avec FLAG_MUTABLE, parce que le système doit y ajouter le tag, et depuis Android 12 la référence de PendingIntent exige que chaque PendingIntent déclare sa mutabilité. Le même exemple ajoute FLAG_ACTIVITY_SINGLE_TOP, pour que le tag atteigne l'activité ouverte dans onNewIntent au lieu d'en lancer une seconde copie.
Les filtres et les listes de technologies réduisent ce que l'activité reçoit, avec les mêmes règles que dans le manifeste. Passer null pour les deux fait recevoir à l'activité tous les tags par ACTION_TAG_DISCOVERED, une action que la référence marque comme dépréciée à partir du niveau d'API 37.
La remise se fait dans onNewIntent, et le guide des processus et des fils rappelle que les rappels de cycle de vie s'exécutent toujours sur le fil principal. Tout échange avec le tag doit donc partir ailleurs, puisque la référence de TagTechnology interdit les entrées sorties sur ce fil.
Choisir entre les deux
| Question | Mode lecteur | Dispatch au premier plan |
|---|---|---|
| Comment le tag arrive | Un rappel, onTagDiscovered | Un Intent, dans onNewIntent |
| Émulation de carte pendant ce temps | Suspendue | Inchangée |
| Technologies interrogées | Seulement celles nommées par les drapeaux | Toutes |
| Vérification NDEF et son du système | Peuvent être sautés | Toujours effectués |
| Disponible à partir de | Niveau d'API 19 | Niveau d'API 10 |
Choisissez le mode lecteur quand l'écran existe pour lire des tags : un inventaire, un outil de configuration, un lecteur de carte propriétaire. Le tag va droit à votre code et rien d'autre sur le téléphone ne le lui dispute.
Choisissez le dispatch au premier plan quand les tags sont une entrée parmi d'autres, et que le téléphone doit continuer à payer et à se comporter normalement pendant que votre activité est ouverte.
Questions fréquentes
Pourquoi le téléphone ne paie-t-il plus pendant que mon application est ouverte ?
Le mode lecteur est actif. La référence indique qu'il désactive l'émulation de carte tant que l'activité est au premier plan : réservez-le aux écrans dont la raison d'être est la lecture.
Quels drapeaux employer pour lire un autre téléphone ?
Pour un téléphone qui émule une carte par émulation de carte par l'hôte, la référence recommande FLAG_READER_NFC_A avec FLAG_READER_SKIP_NDEF_CHECK.
Faut-il quand même des filtres d'Intent dans le manifeste ?
Seulement pour les tags qui doivent lancer l'application quand elle n'est pas ouverte. Ni le mode lecteur ni le dispatch au premier plan ne s'appliquent avant qu'une activité soit à l'écran.
Pourquoi enableForegroundDispatch lève-t-il IllegalStateException ?
Il a été appelé alors que l'activité n'était pas au premier plan, depuis onCreate par exemple. Activez-le dans onResume et désactivez-le dans onPause.