¿Por qué un lector llega a otra aplicación en vez de a la tuya?
Porque otro servicio ha registrado el mismo identificador, y Android resuelve el conflicto antes de que se ejecute tu código: gana la aplicación de cartera por defecto, luego el único servicio registrado, y si no se le pregunta a quien usa el teléfono. Una actividad en primer plano puede invertir el resultado con setPreferredService.
La tabla de encaminamiento decide primero
El controlador NFC guarda una tabla de encaminamiento: una lista finita de reglas, cada una emparejando un identificador con un destino, el procesador principal donde se ejecutan las aplicaciones o un elemento seguro conectado. Cuando un lector envía un SELECT, el controlador empareja el identificador y manda ese comando y todos los siguientes a ese destino, hasta que llega otro SELECT o se rompe el enlace. La guía de Android sobre la emulación de tarjeta describe la tabla y dice que las aplicaciones no la configuran nunca; la plataforma la construye a partir de los servicios instalados y de lo que haya elegido quien usa el teléfono.
De ahí salen dos consecuencias. Los emparejamientos parciales, que la ISO/IEC 7816-4 permite, no los admite la emulación de tarjeta de Android, así que un identificador empareja entero o no empareja. Y la tabla tiene un tamaño, aunque la guía exige que los aparatos encaminen hacia el procesador principal los identificadores que tu aplicación ha registrado.
Cómo resuelve Android un conflicto
Varios servicios pueden registrar el mismo identificador, y la guía da el orden. Gana la aplicación de cartera por defecto si ha registrado el identificador. Si no, se invoca al único servicio que lo haya registrado. Y si lo han registrado varios, Android pregunta cuál usar.
La categoría de pago estrecha esto todavía más. Solo hay un grupo de pago activo a la vez en el aparato, y una aplicación que registra identificadores de pago solo hace la transacción como titular del papel de cartera, desde Android 15, o desde el primer plano. Un sistema que funciona en un solo comercio va en la otra categoría, cuyos grupos pueden quedarse activos todo el tiempo y que no compite por esa única plaza.
Una aplicación puede pedir el papel en lugar de esperarlo: RoleManager.ROLE_WALLET con createRequestRoleIntent, e isRoleHeld para saber cómo anda.
Lo que cambia una actividad en primer plano
setPreferredService nombra el servicio que hay que preferir mientras una actividad esté en curso, e invierte la resolución de arriba. La referencia de CardEmulation lo pide en onResume y pide unsetPreferredService en onPause, ya que el sistema no conserva la preferencia: hay que volver a ponerla cada vez que la actividad vuelve.
La llamada falla en dos casos, ambos sobre el pago. Si el servicio registra identificadores de pago y quien usa el teléfono no permite que las aplicaciones en primer plano invaliden el servicio de pago por defecto. Y si registra identificadores de la otra categoría que el servicio de pago por defecto también trata, bajo esa misma elección. categoryAllowsForegroundPreference responde antes de que lo intentes.
Qué comprobar cuando un toque va a otro sitio
Pregúntale a la plataforma qué opina. isDefaultServiceForCategory responde por una categoría, pero la referencia avisa de que siempre devuelve falso cuando el modo de selección es preguntar siempre o preguntar en caso de conflicto; en esos modos, isDefaultServiceForAid es la pregunta que tiene sentido. getSelectionModeForCategory te dice en qué modo estás.
Después mira fuera de tu aplicación. Otra aplicación instalada puede registrar el mismo identificador, y un servicio fuera de host puede reclamarlo para un elemento seguro, en cuyo caso el intercambio no llega nunca a ningún código del procesador principal. Leer los identificadores que ha registrado tu servicio, y compararlos con lo que selecciona el lector, resuelve la mayoría de estos casos más rápido que razonarlos: la página de las APDU cubre el SELECT en sí.
Preguntas frecuentes
¿Quién gana cuando dos aplicaciones registran el mismo identificador?
La aplicación de cartera por defecto, si lo ha registrado. Si no, el único servicio que lo haya hecho, y si lo han hecho varios, Android pregunta.
¿Por qué devuelve falso setPreferredService?
El servicio registra identificadores de pago, o identificadores que el servicio de pago por defecto también trata, y no se permite que el primer plano invalide ese servicio.
¿Empareja Android una parte de un identificador?
No. Los emparejamientos parciales existen en la ISO/IEC 7816-4, pero la emulación de tarjeta de Android no los admite.
¿Cómo se convierte una aplicación en la cartera por defecto?
Pidiendo el papel de cartera con RoleManager.createRequestRoleIntent, y comprobándolo con isRoleHeld. Lo concede quien usa el teléfono.