¿Por qué expira un comando, y cuánto debe esperar el código?
Android deja fijar una espera por tecnología y la devuelve a su valor por defecto al cerrar la conexión; ese valor por defecto no está documentado, así que léelo en vez de suponerlo. iOS no expone ninguna espera. En los dos casos la respuesta a una expiración suele ser menos comandos y no una espera más larga.
Lo que expone Android
setTimeout() en NfcA o en IsoDep fija cuánto espera transceive(). Dos detalles de la referencia deciden cómo se usa: el valor vuelve a su valor por defecto cuando la conexión se cierra, así que se pone otra vez después de cada connect(), y ese valor por defecto no está documentado, así que getTimeout() es la única manera honesta de conocerlo.
Un valor más largo es para las operaciones que le llevan tiempo a la etiqueta, y la generación de una clave es el ejemplo de la propia referencia. No hace responder a una etiqueta que no iba a responder, y no ayuda con una etiqueta que se ha ido, que lanza TagLostException en su lugar, el asunto de la página de la etiqueta perdida.
El modo lector añade un segundo reloj: el intervalo con el que la plataforma comprueba que una etiqueta detectada sigue presente, que se fija por el extra de comprobación de presencia y que cubre la página de la retirada.
Lo que iOS no expone
Core NFC no tiene ninguna espera que fijar. La app envía un comando y espera, y el marco de trabajo informa con readerTransceiveErrorRetryExceeded cuando ha habido demasiados reintentos, o con un error de conexión perdida cuando la etiqueta se ha ido.
La sesión tiene su propio límite, una invalidación sin duración documentada, que retoma la página de la invalidación. Así que en iOS la única palanca es cuánto pide la app y con qué rapidez responde: en emulación de tarjeta, Apple avisa de que un lector puede leer una respuesta lenta como un tiempo agotado.
Lo que cuesta una ida y vuelta
Cada comando es una ida y vuelta, y el presupuesto de un toque es pequeño. La guía de la emulación de tarjeta de Android pone un límite superior razonable en torno a 1 KB de datos intercambiados en unos 300 ms, que es el baremo publicado más claro de lo que cabe mientras una mano se sostiene quieta.
Así que lee en los bloques que te dé el protocolo. Un READ de tipo 2 devuelve cuatro páginas de una vez, dieciséis bytes por un comando, como describe la página del tipo 2; una lectura de tipo 4 está limitada por el máximo del propio contenedor, y pedir menos de ese máximo cuesta comandos que no compran nada.
Diseñar dentro de la ventana
Haz el trabajo antes del toque. Trae lo que el intercambio necesita, construye las tramas, abre la conexión de red, y guarda el tiempo de la etiqueta para la etiqueta: una app que llama a un servidor mientras sostiene una etiqueta ha puesto una red en el camino crítico de un gesto de la mano.
Y luego trata una expiración como desconocida en vez de como fallida, sobre todo después de una escritura, y lee la etiqueta de vuelta antes de decidir nada. Un reintento que supone que el comando anterior no hizo nada es la manera de incrementar un contador dos veces.
Preguntas frecuentes
¿Cuál es la espera por defecto en Android?
No está documentada. Léela con getTimeout en la tecnología que hayas abierto, y vuelve a poner tu valor después de cada connect.
¿Puedo fijar una espera en iOS?
No. Core NFC no expone ninguna. Informa de demasiados reintentos o de una conexión perdida, y la sesión tiene su propio límite sin documentar.
¿Cuánto puedo intercambiar en un toque?
La guía de la emulación de tarjeta de Android da en torno a 1 KB en unos 300 ms como límite razonable, y sirve de baremo también para leer.
¿Es lo mismo una expiración que un rechazo?
No. Un rechazo vuelve como unos bytes de estado o una marca de error de la etiqueta. Una expiración significa que no ha vuelto nada, así que el resultado es desconocido.