Aller au contenu
Langue : FR

Comment déclarer les tags qu'une application Android doit recevoir ?

Par des filtres d'Intent sur le contenu NDEF d'abord, par une liste de technologies ensuite, le niveau fourre tout ne servant qu'en dernier recours. Deux changements récents pèsent plus que le reste : un lien web ne passe plus par le niveau NDEF depuis Android 16, et Android 17 demande une permission sur chaque activité qui reçoit un tag.

Trois niveaux, un seul gagnant

Deux déclarations viennent avant tout filtre : la permission android.permission.NFC et, pour une application qui ne sert à rien sans NFC, la fonctionnalité android.hardware.nfc marquée comme requise, dont Google Play se sert pour masquer l'application aux téléphones dépourvus du matériel.

Le guide des bases du NFC énumère ensuite trois Intents de distribution, du plus prioritaire au moins prioritaire : ACTION_NDEF_DISCOVERED pour un tag dont le contenu NDEF correspond à un type, ACTION_TECH_DISCOVERED quand aucune activité ne traite le premier, et ACTION_TAG_DISCOVERED en dernier recours.

La distribution s'arrête au premier niveau où une activité correspond. Si plusieurs correspondent à ce niveau, l'utilisateur obtient un sélecteur, que la référence de Tag présente comme le résultat que la conception cherche à éviter, puisque déplacer le téléphone pour choisir rompt en général la connexion.

Le niveau NDEF ne lit qu'un enregistrement. La même référence indique que le système examine le premier enregistrement du premier message : un message qui s'ouvre sur un enregistrement que votre application ignore est donc, pour la distribution, un message qui parle d'autre chose.

Ce que devient le premier enregistrement
Premier enregistrementDistribué comme
Type bien connu, URIUne URI construite depuis la charge utile
Type bien connu, texteLe type MIME text/plain
Média MIMELe type MIME que l'enregistrement déclare
URI absolueUne URI construite depuis le champ de type
Type externeUne URI commençant par vnd.android.nfc://ext/
Vide, inconnu ou inchangéRien : la distribution retombe sur les technologies

Filtrer sur le contenu

Un filtre ACTION_NDEF_DISCOVERED nomme l'action, la catégorie DEFAULT et un élément data : un type MIME, ou un schéma avec un hôte et un chemin.

Écrivez chaque partie en minuscules. La référence d'IntentFilter précise que la comparaison du type MIME, du schéma et de l'hôte est sensible à la casse, contrairement aux RFC dont ils viennent. Quand un enregistrement est converti en URI, la référence de NdefRecord indique que le schéma passe en minuscules et ne dit rien de l'hôte : un tag écrit avec une majuscule dans l'hôte peut donc manquer un filtre écrit en minuscules.

Filtrez sur ce que votre application traite, et pas plus large. L'exemple de dispatch au premier plan du guide NFC avancé enregistre tous les types MIME avec un commentaire qui demande de ne nommer que ceux dont on a besoin, et un filtre trop large met l'application dans le sélecteur pour des tags dont elle ne sait rien faire.

Le plus gros changement récent porte sur le tag le plus répandu. Depuis Android 16, indique le guide des bases du NFC, un tag qui porte un lien http ou https déclenche ACTION_VIEW au lieu d'ACTION_NDEF_DISCOVERED.

Depuis Android 17, le même tag affiche d'abord une notification d'ouverture de lien, et le lien ne s'ouvre que si l'utilisateur agit dessus.

Une application qui filtrait sur sa propre adresse https par ACTION_NDEF_DISCOVERED cesse donc de recevoir ces tags sur ces versions. La documentation renvoie aux liens d'application Android pour ouvrir une application depuis un tel lien.

Le changement ne vise que http et https. La documentation ne décrit rien de semblable pour les enregistrements MIME, les types externes ou les autres schémas, qui continuent de passer par le niveau NDEF.

Listes de technologies

ACTION_TECH_DISCOVERED demande un filtre d'Intent et une entrée meta-data qui pointe vers une ressource XML d'éléments tech-list. La référence de NfcAdapter en donne la logique : toutes les technologies d'une même tech-list doivent être présentes, et une seule tech-list suffit.

Ne nommez que des classes que tous les téléphones visés fournissent. La référence de TagTechnology rend MifareClassic, MifareUltralight et NfcBarcode facultatives, et un téléphone qui n'en a pas une ne la liste jamais : une liste de technologies qui l'exige ne correspond donc jamais sur ce téléphone, et rien ne le signale.

Ce qu Android 16 et 17 exigent

Depuis Android 17, une application qui vise un SDK supérieur à Android 16 doit protéger chaque activité recevant des Intents NFC par android.permission.DISPATCH_NFC_MESSAGE, pour que seul le service système NFC puisse la lancer. Le même passage ajoute que le système ne distribue pas d'Intent NFC à une application dans l'état arrêté : jamais lancée par l'utilisateur, ou arrêtée de force.

Depuis Android 16, l'utilisateur peut refuser les Intents de tag application par application. isTagIntentAppPreferenceSupported() dit si le téléphone propose le réglage, isTagIntentAllowed() si l'utilisateur a laissé votre application autorisée, et ACTION_CHANGE_TAG_INTENT_PREFERENCE ouvre la page où cela se change.

Et ACTION_TAG_DISCOVERED, le niveau fourre tout, est déprécié depuis Android 17, ce qui laisse les filtres de contenu et les listes de technologies comme les deux portes d'entrée prises en charge.

Questions fréquentes

Pourquoi mon filtre NDEF ne se déclenche-t-il jamais ?

Vérifiez la casse du type MIME, du schéma et de l'hôte, puis le premier enregistrement du tag. À partir d'Android 16, vérifiez si le tag porte un lien web, et sur Android 17 si l'activité porte la permission de distribution.

Pourquoi un sélecteur apparaît-il alors que mon application est installée ?

Une autre application correspond au même niveau. Resserrez votre filtre sur un contenu que vous seul traitez, ou nommez votre application sur le tag par un Android Application Record.

Un Android Application Record remplace-t-il les filtres d'Intent ?

Non. Le système essaie d'abord les filtres. Si l'activité qui correspond n'appartient pas à l'application nommée, ou si plusieurs correspondent, il lance l'application nommée, et ouvre Google Play quand elle n'est pas installée.

Mon application peut-elle encore recevoir un tag qui porte un lien web ?

Par les liens d'application Android, vers lesquels la documentation renvoie depuis Android 16. Un filtre NDEF sur l'adresse https ne reçoit plus le tag, et depuis Android 17 le lien attend une action de l'utilisateur sur une notification.