¿Cómo se detecta que una etiqueta ha salido del campo?
En Android, el intercambio siguiente lanza TagLostException, y desde el nivel de API 24 NfcAdapter.ignore() llama a un oyente cuando la etiqueta lleva fuera un retardo elegido. En iOS, isAvailable pasa a falso. Ninguna de las dos declara el momento mismo, y una etiqueta que vuelve cuenta como nueva, la causa habitual de las lecturas dobles.
En Android
El flujo corriente no tiene ningún suceso de retirada. La plataforma comprueba que una etiqueta descubierta sigue presente, y el modo lector deja a una aplicación fijar cada cuánto mediante EXTRA_READER_PRESENCE_CHECK_DELAY, que la referencia de NfcAdapter describe como el retardo que la plataforma usa para las comprobaciones de presencia. Lo que la aplicación ve es su llamada de entrada y salida siguiente fallando con TagLostException, una subclase de IOException.
isConnected() no responde a la pregunta. La referencia de TagTechnology dice que devuelve verdadero cuando connect() se ha completado, close() no se ha llamado y no se sabe que la etiqueta esté fuera de alcance, sin ninguna actividad de radio: declara lo que la plataforma ya sabe, no una comprobación fresca.
Para una etiqueta que se queda en su sitio, como una en un soporte de coche, NfcAdapter.ignore(), desde el nivel de API 24, es la herramienta. Corta la comunicación con la etiqueta mientras siga en alcance y llama a un OnTagRemovedListener cuando la etiqueta lleva fuera de alcance debounceMs; una etiqueta que vuelve antes no se despacha otra vez. La referencia añade tres límites: el controlador sondea cada 100 a 500 ms, así que una etiqueta que entra y sale de alcance puede despacharse otra vez aunque nunca se fuera de verdad; otra etiqueta cancela la llamada; y una etiqueta con identificador aleatorio la derrota.
En iOS
Toda etiqueta que entrega Core NFC hereda de NFCNDEFTag, cuyo isAvailable pasa a falso cuando la etiqueta se retira del campo o se desconecta, según la referencia de isAvailable. Ninguna llamada al delegado lo declara: una aplicación que necesita saberlo lee la propiedad, o se entera por un comando que falla con readerTransceiveErrorTagConnectionLost.
Una conexión puede terminar además con la etiqueta todavía ahí. Una etiqueta sigue conectada hasta que la aplicación se conecta a otra o reinicia el sondeo, según la referencia de connect, y la nota de Apple sobre restartPolling() dice que las etiquetas detectadas antes de un reinicio dejan de valer.
Una sesión NDEF espera ella misma. Con un delegado que recibe mensajes, la sesión reinicia el sondeo cuando las etiquetas detectadas salen de alcance, como explica la página de las varias etiquetas, así que una etiqueta sostenida en su sitio no se lee dos veces seguidas.
Por qué siempre llega tarde
La retirada se deduce del silencio. Un teléfono se entera de que una etiqueta se ha ido cuando una comprobación de presencia o un comando no obtienen respuesta, y la referencia de NfcAdapter pone el intervalo de sondeo del controlador entre 100 y 500 ms. La aplicación se entera de la retirada después de que la mano se haya movido, nunca en el momento en que se mueve.
Diseña la interfaz en torno a ese retraso. Una escritura declarada hecha antes de que su llamada volviera es una suposición: enseña que ha terminado cuando la llamada vuelve, y trata una excepción como un resultado desconocido, como explica la página de las escrituras interrumpidas.
Las lecturas dobles empiezan aquí
Una etiqueta que se va y vuelve es un descubrimiento nuevo. En Android llega como un objeto Tag nuevo, ya que la referencia de Tag crea uno cada vez que la etiqueta entra en alcance; en iOS la sesión la detecta otra vez una vez que se ha ido. La página del disparo doble describe cómo una mano produce esto sin querer.
Una aplicación que tiene que actuar una vez por toque decide por tanto qué cuenta como repetición. Comparar el identificador con el último leído, dentro de una ventana de tiempo que la aplicación elige, atrapa el caso corriente, y ignore() hace lo mismo en Android para una etiqueta dejada en su sitio. Ninguno de los dos funciona con identificadores aleatorios, donde el lado que recibe tiene que tolerar repeticiones, la conclusión a la que llega la página del disparo doble para los servidores.
Preguntas frecuentes
¿isConnected() me dice que la etiqueta sigue ahí?
No. Declara si connect se completó y close no se ha llamado, sin tocar la radio. La llamada de entrada y salida siguiente es la que te lo dice.
¿Hay un suceso cuando una etiqueta se va en Android?
Solo mediante NfcAdapter.ignore(), desde el nivel de API 24, cuyo oyente se dispara cuando la etiqueta lleva fuera de alcance el retardo que fijes.
¿Lo hay en iOS?
Ninguna llamada al delegado lo declara. La propiedad isAvailable de la etiqueta pasa a falso, y el comando siguiente falla con un error de conexión perdida.
¿Por qué mi app lee la misma etiqueta dos veces?
La etiqueta salió del campo y volvió, lo que cuenta como un descubrimiento nuevo. Compara identificadores dentro de una ventana de tiempo, o usa ignore() en Android para una etiqueta que se queda en su sitio.