¿Cómo se declaran las etiquetas que debe recibir una app Android?
Con filtros de intent en el manifiesto, resueltos en un orden fijo: primero el contenido NDEF, después las listas de tecnologías. Filtra sobre el contenido que tu aplicación trata, en minúsculas. Dos cambios recientes deciden si llega algo: los enlaces web van a ACTION_VIEW desde Android 16, y Android 17 exige el permiso de despacho NFC en la actividad.
Tres niveles, un solo ganador
Dos declaraciones van antes que cualquier filtro: el permiso android.permission.NFC y, para una aplicación que no sirve de nada sin NFC, la característica android.hardware.nfc marcada como obligatoria, que Google Play usa para esconder la aplicación en los teléfonos sin el aparato.
La guía del marco de trabajo NFC enumera después tres intents de despacho, de mayor a menor prioridad: ACTION_NDEF_DISCOVERED para una etiqueta cuyo contenido NDEF corresponde a un tipo, ACTION_TECH_DISCOVERED cuando ninguna actividad trata el primero, y ACTION_TAG_DISCOVERED como último recurso.
El despacho se detiene en el primer nivel donde encaja una actividad. Si encajan varias en ese nivel, a quien usa el teléfono le sale un selector, que la referencia de Tag presenta como el resultado que el diseño intenta evitar, ya que mover el teléfono para elegir suele romper la conexión.
El nivel NDEF lee un solo registro. La misma referencia dice que el sistema examina el primer registro del primer mensaje, así que un mensaje que empieza por un registro que tu aplicación ignora es, para el despacho, un mensaje sobre otra cosa.
| Primer registro | Se despacha como |
|---|---|
| Tipo conocido, URI | Un URI construido a partir de la carga |
| Tipo conocido, texto | El tipo MIME text/plain |
| Medio MIME | El tipo MIME que declara el registro |
| URI absoluto | Un URI construido a partir del campo de tipo |
| Tipo externo | Un URI que empieza por vnd.android.nfc://ext/ |
| Vacío, desconocido o sin cambiar | Nada: el despacho recae en las tecnologías |
Filtrar sobre el contenido
Un filtro ACTION_NDEF_DISCOVERED nombra la acción, la categoría DEFAULT y un elemento data: un tipo MIME, o un esquema con un host y una ruta.
Escribe cada parte en minúsculas. La referencia de IntentFilter declara que el tipo MIME, el esquema y el host distinguen mayúsculas de minúsculas, al revés que los RFC de los que vienen. Cuando un registro se convierte en URI, la referencia de NdefRecord dice que el esquema pasa a minúsculas y no dice nada del host, así que una etiqueta escrita con un host en mayúsculas puede no encajar con un filtro escrito en minúsculas.
Filtra sobre lo que tu aplicación trata y nada más ancho. El ejemplo de despacho en primer plano de la guía NFC avanzada registra todos los tipos MIME con un comentario que pide nombrar solo los que hagan falta, y un filtro demasiado ancho mete la aplicación en el selector para etiquetas que no sabe usar.
Los enlaces web ya no son intents NDEF
El mayor cambio reciente afecta a la etiqueta más corriente. Desde Android 16, dice la guía del marco de trabajo NFC, una etiqueta que contiene un enlace http o https dispara ACTION_VIEW en lugar de ACTION_NDEF_DISCOVERED.
Desde Android 17, la misma etiqueta muestra primero un aviso de abrir enlace, y el enlace se abre solo cuando alguien actúa sobre él.
Una aplicación que filtraba sobre su propia dirección https mediante ACTION_NDEF_DISCOVERED deja por tanto de recibir esas etiquetas en esas versiones. La documentación remite a los Android App Links para abrir una aplicación desde un enlace así.
El cambio se limita a http y https. La documentación no describe nada parecido para los registros MIME, los tipos externos ni otros esquemas, que siguen pasando por el nivel NDEF.
Listas de tecnologías
ACTION_TECH_DISCOVERED necesita un filtro de intent y una entrada meta-data que apunte a un recurso XML de elementos tech-list. La referencia de NfcAdapter deletrea la lógica: cada tecnología dentro de una tech-list tiene que estar presente, y basta con que encaje una sola tech-list.
Nombra solo clases que ofrezcan todos los teléfonos a los que apuntas. La referencia de TagTechnology hace opcionales MifareClassic, MifareUltralight y NfcBarcode, y un teléfono al que le falta una no la enumera nunca, así que una lista de tecnologías que la exige no encaja nunca en ese teléfono, y nada lo avisa.
Lo que exigen Android 16 y 17
Desde Android 17, una aplicación que apunta a un SDK por encima de Android 16 tiene que proteger cada actividad que recibe intents NFC con android.permission.DISPATCH_NFC_MESSAGE, para que solo el servicio NFC del sistema pueda arrancarla. El mismo pasaje añade que el sistema no despacha intents NFC a una aplicación en estado detenido: nunca lanzada por quien usa el teléfono, o parada a la fuerza.
Desde Android 16, se pueden rechazar los intents de etiqueta aplicación por aplicación. isTagIntentAppPreferenceSupported() dice si el teléfono ofrece el ajuste, isTagIntentAllowed() si tu aplicación sigue permitida, y ACTION_CHANGE_TAG_INTENT_PREFERENCE abre la página donde se cambia.
Y ACTION_TAG_DISCOVERED, el nivel que lo recoge todo, queda obsoleto desde Android 17, lo que deja los filtros de contenido y las listas de tecnologías como las dos vías admitidas.
Preguntas frecuentes
¿Por qué mi filtro NDEF no se dispara nunca?
Mira las mayúsculas del tipo MIME, del esquema y del host, y después el primer registro de la etiqueta. En Android 16 y posteriores, mira si la etiqueta contiene un enlace web, y en Android 17 si la actividad lleva el permiso de despacho.
¿Por qué sale un selector si mi aplicación está instalada?
Otra aplicación encaja en el mismo nivel. Estrecha tu filtro a contenido que solo trate la tuya, o nombra tu aplicación en la etiqueta con un Android Application Record.
¿Un Android Application Record sustituye a los filtros de intent?
No. El sistema prueba primero los filtros. Si la actividad que encaja no pertenece a la aplicación nombrada, o si encajan varias, arranca la aplicación nombrada, y abre Google Play cuando esa aplicación no está instalada.
¿Mi aplicación puede seguir recibiendo una etiqueta con un enlace web?
Mediante los Android App Links, a los que la documentación remite desde Android 16. Un filtro NDEF sobre la dirección https ya no recibe la etiqueta, y desde Android 17 el enlace espera a que alguien actúe sobre un aviso.