Quelles limites du contrôleur le code Android doit-il vérifier ?
Quatre, et chacune a son accesseur : la taille maximale d'une trame, la prise en charge des APDU de longueur étendue, le délai d'attente d'une réponse et la présence des classes facultatives. Aucune n'a de valeur à supposer, et un code qui recopie celles d'un téléphone échoue sur un autre.
Ce qu une commande peut porter
getMaxTransceiveLength(), sur NfcA, NfcV ou IsoDep, rend le plus grand nombre d'octets qu'un appel à transceive() peut envoyer. Il dépend du contrôleur du téléphone, et la référence ne donne aucune valeur à supposer.
Les APDU ajoutent une seconde limite. La référence d'IsoDep explique qu'un APDU standard porte au plus 255 octets de charge utile, 261 octets en tout, alors qu'un APDU de longueur étendue en porte jusqu'à 65535, et que certains adaptateurs ne prennent pas en charge la forme étendue. isExtendedLengthApduSupported() répond pour le téléphone que vous tenez.
Une carte qui attend des APDU étendus fonctionne donc sur un téléphone et échoue sur un autre avec le même code. Là où la carte accepte aussi la forme standard, repliez-vous dessus plutôt que de supposer la prise en charge.
Combien de temps le téléphone attend
setTimeout() sur NfcA ou IsoDep fixe la durée pendant laquelle transceive() attend une réponse. La référence de NfcA suggère une valeur plus longue pour les opérations qui prennent du temps au tag, une génération de clé par exemple, et note que la valeur revient à son défaut à la fermeture de la connexion.
Le défaut lui même n'est pas documenté. Lisez-le avec getTimeout() au lieu de figer le chiffre mesuré sur un téléphone, et reposez votre propre valeur après chaque connect().
Quelles classes existent
Les classes facultatives sont l'autre variable. MifareClassic, MifareUltralight et NfcBarcode peuvent manquer entièrement à un téléphone, et NdefFormatable n'apparaît que pour les tags que le téléphone sait formater.
Le seul test fiable est getTechList() sur le tag que vous tenez, puisque l'absence est silencieuse. La page des classes de technologie couvre ce que chacune apporte.
Ce que l'utilisateur et le système coupent
getDefaultAdapter() rend null quand le téléphone n'a pas de contrôleur NFC, et isEnabled() rend false quand l'utilisateur a coupé le NFC. La référence de NfcAdapter suggère d'envoyer l'utilisateur vers Settings.ACTION_NFC_SETTINGS dans le second cas.
Depuis Android 16, un utilisateur peut aussi refuser les Intents de tag pour une seule application, ce que rapporte isTagIntentAllowed(). L'adaptateur est actif, l'application est installée, et les tags n'arrivent pourtant jamais : cela vaut d'être vérifié avant tout débogage.
Depuis le niveau d'API 34, getNfcAntennaInfo() rend ce que le téléphone sait de ses antennes, position relative comprise, et peut rendre null. Là où il répond, une application peut montrer à l'utilisateur où tenir le tag au lieu de le lui décrire avec des mots.
Questions fréquentes
Quelle longueur de trame peut-on supposer ?
Aucune. Lisez getMaxTransceiveLength sur la technologie connectée et découpez les commandes pour qu'elles tiennent.
Pourquoi un APDU passe-t-il sur un téléphone et échoue-t-il sur un autre ?
Il emploie peut-être la forme de longueur étendue, que certains adaptateurs ne prennent pas en charge. Vérifiez isExtendedLengthApduSupported et repliez-vous sur des APDU standard là où la carte le permet.
Un délai posé par setTimeout persiste-t-il ?
Non. La référence indique qu'il revient au défaut à la fermeture de la connexion : reposez-le après chaque connect.
Une application peut-elle savoir où se trouve l'antenne NFC ?
Depuis le niveau d'API 34, getNfcAntennaInfo rend les informations d'antenne, position relative comprise, quand le téléphone les fournit. Il peut rendre null, donc l'application a besoin d'un repli.