Perché un lettore raggiunge un'altra applicazione invece della tua?
Perché un altro servizio ha registrato lo stesso identificatore, e Android risolve il conflitto prima che il tuo codice giri: vince l'applicazione portafoglio predefinita, poi il servizio unico registrato, e altrimenti viene chiesto a chi usa il telefono. Un'attività in primo piano può scavalcare l'esito con setPreferredService.
Decide prima la tabella di instradamento
Il controller NFC porta una tabella di instradamento: un elenco finito di regole, ciascuna delle quali accoppia un identificatore a una destinazione, il processore host dove girano le applicazioni o un elemento sicuro collegato. Quando un lettore invia una SELECT, il controller confronta l'identificatore e manda quel comando e ogni comando successivo a quella destinazione, finché non arriva un'altra SELECT o il collegamento non si rompe. La guida all'emulazione di scheda di Android descrive la tabella e dice che le applicazioni non la configurano mai; è la piattaforma a costruirla dai servizi installati e da quello che chi usa il telefono ha scelto.
Ne seguono due conseguenze. Le corrispondenze parziali, che la ISO/IEC 7816-4 consente, non sono sostenute da Host Card Emulation di Android, quindi un identificatore corrisponde per intero o non corrisponde. E la tabella ha una dimensione, anche se la guida esige che i dispositivi instradino verso l'host gli identificatori che la tua applicazione ha registrato.
Come Android risolve un conflitto
Più servizi possono registrare lo stesso identificatore, e la guida dà l'ordine. Vince l'applicazione portafoglio predefinita se ha registrato l'identificatore. In mancanza di questo, viene invocato il servizio unico che l'ha registrato. Se più di uno l'ha fatto, Android chiede a chi usa il telefono quale usare.
La categoria del pagamento restringe ancora la cosa. Sul dispositivo è attivo un gruppo di pagamento solo alla volta, e un'applicazione che registra identificatori di pagamento fa transazioni soltanto come portatrice del ruolo di portafoglio, da Android 15, o dal primo piano. Uno schema che funziona presso un solo esercente sta nell'altra categoria, i cui gruppi possono restare attivi sempre e che non si contende quel posto unico.
Un'applicazione può chiedere il ruolo invece di sperarlo: RoleManager.ROLE_WALLET con createRequestRoleIntent, e isRoleHeld per sapere a che punto sta.
Che cosa cambia un'attività in primo piano
setPreferredService nomina il servizio da preferire mentre un'attività è ripresa, e scavalca la risoluzione qui sopra. Il riferimento di CardEmulation lo chiede in onResume e chiede unsetPreferredService in onPause, dato che il sistema non conserva la preferenza: va rimessa ogni volta che l'attività riprende.
La chiamata fallisce in due casi, tutti e due legati al pagamento. Se il servizio registra identificatori di pagamento e chi usa il telefono non consente alle applicazioni in primo piano di scavalcare il servizio di pagamento predefinito. E se registra identificatori dell'altra categoria che anche il servizio di pagamento predefinito tratta, sotto la stessa scelta. categoryAllowsForegroundPreference risponde prima che tu provi.
Che cosa verificare quando un tocco va altrove
Chiedi alla piattaforma che cosa ne pensa. isDefaultServiceForCategory risponde per una categoria, ma il riferimento avverte che rende sempre falso quando il modo di selezione è chiedi sempre o chiedi in caso di conflitto; in quei modi, isDefaultServiceForAid è la domanda che ha senso. getSelectionModeForCategory ti dice in quale modo sei.
Poi guarda fuori dalla tua applicazione. Un'altra applicazione installata può registrare lo stesso identificatore, e un servizio fuori host può rivendicarlo per un elemento sicuro, nel qual caso lo scambio non raggiunge mai alcun codice sull'host. Leggere gli identificatori che il tuo servizio ha registrato, e confrontarli con quello che il lettore seleziona, risolve quasi tutti questi casi più in fretta che ragionarci: la pagina delle APDU copre la SELECT stessa.
Domande frequenti
Chi vince quando due applicazioni registrano lo stesso identificatore?
L'applicazione portafoglio predefinita, se l'ha registrato. Altrimenti il servizio unico che l'ha fatto, e se sono stati diversi, Android chiede a chi usa il telefono.
Perché setPreferredService rende falso?
Il servizio registra identificatori di pagamento, o identificatori che anche il servizio di pagamento predefinito tratta, e chi usa il telefono non ha consentito alle applicazioni in primo piano di scavalcare quel servizio.
Android confronta una parte di un identificatore?
No. Le corrispondenze parziali esistono nella ISO/IEC 7816-4 ma Host Card Emulation di Android non le sostiene.
Come diventa portafoglio predefinita un'applicazione?
Chiedendo il ruolo di portafoglio con RoleManager.createRequestRoleIntent, e verificando con isRoleHeld. È chi usa il telefono a concederlo.