Ir para o conteúdo
Idioma: PT

Como um aplicativo Android emula um cartão com emulação de cartão pelo host?

Com um serviço que estende HostApduService e responde a APDU, declarado no manifesto com o filtro de intent de emulação de cartão, a permissão BIND_NFC_SERVICE e um arquivo XML que registra os identificadores de aplicação dele numa categoria. O Android inicia o serviço num toque, mesmo com o aplicativo fechado.

O serviço e os dois métodos dele

A emulação vive num serviço, não numa atividade. O guia da emulação de cartão do Android constrói o mecanismo sobre HostApduService, que roda em segundo plano: um toque o inicia se ele não estiver rodando, e a transação acontece sem o aplicativo ser aberto. Confira FEATURE_NFC_HOST_CARD_EMULATION antes de contar com qualquer parte disso, e a declare com uses-feature no manifesto.

A classe tem dois métodos a implementar. processCommandApdu() é chamado para cada APDU que o leitor envia, e devolve os bytes da resposta. Ele roda na linha de execução principal, então uma resposta que dá trabalho devolve null e chega depois por sendResponseApdu() a partir de outra linha. onDeactivated() é chamado quando o leitor seleciona um identificador que resolve para outro serviço, ou quando o enlace de rádio se rompe, e o argumento dele diz qual dos dois aconteceu.

O que viaja é uma APDU, como descreve a página das APDU. O Android emula ISO-DEP, a ISO/IEC 14443-4, e processa os comandos da ISO/IEC 7816-4; o guia exige ISO-DEP sobre NFC-A e deixa NFC-B opcional. A troca é semiduplex e o Android suporta um único canal lógico, então comandos e respostas se alternam um de cada vez.

O que o manifesto e o XML declaram

A declaração do serviço carrega três acréscimos: um filtro de intent para a ação de serviço APDU no host, a permissão android.permission.BIND_NFC_SERVICE com android:exported em verdadeiro, e uma tag meta-data que aponta para um recurso XML. A permissão é do sistema, então exigi-la quer dizer que só o sistema operacional consegue se ligar ao serviço. O aplicativo também guarda a permissão de NFC.

O arquivo XML é onde os identificadores vivem. A raiz dele, host-apdu-service, carrega uma descrição destinada ao usuário e, opcionalmente, requireDeviceUnlock. Ela contém uma ou mais tags aid-group, cada uma com a descrição dela, uma categoria, e uma ou mais tags aid-filter que guardam um único identificador cada, escrito em hexadecimal com um número par de caracteres.

Um serviço que responde a partir de um elemento seguro em vez de a partir do seu código se declara do mesmo jeito, com a ação fora do host e uma raiz offhost-apdu-service. O Android não tem API para falar diretamente com um elemento seguro, o que a página do elemento seguro põe em contexto.

Grupos de identificadores e categorias

Um identificador de aplicação tem até dezesseis bytes, e o leitor o nomeia num comando SELECT. O guia recomenda registrar o seu sob a ISO/IEC 7816-5 quando você instala os seus próprios leitores, para que ele não colida com ninguém. Os identificadores que andam juntos vão num grupo, e o Android encaminha um grupo por inteiro: ou cada identificador dele chega ao seu serviço, ou nenhum chega.

Cada grupo declara uma categoria, pagamento ou outra. Só um grupo de pagamento pode ficar ativado no aparelho de cada vez, e um aplicativo que registra identificadores de pagamento só faz transação quando guarda o papel de carteira, a partir do Android 15, ou quando está em primeiro plano e chamou setPreferredService. Um esquema de circuito fechado, utilizável num só comerciante, pertence à outra categoria, onde os grupos conseguem ficar ativos o tempo todo. Que serviço um leitor de fato alcança é o assunto da página do encaminhamento.

O que a troca tem de respeitar

Mantenha ela curta. O guia põe um limite superior razoável em cerca de 1 KB de dados, trocáveis em uns 300 ms, e esse orçamento decide quanto tempo um usuário tem de segurar o celular contra o leitor.

Mantenha ela dentro do que a plataforma emula. A emulação de cartão pelo host responde à troca de comandos da norma; um esquema cuja segurança fica abaixo dessa camada, o MIFARE Classic entre eles, não dá para emular, como explica a página da emulação de cartão pelo host a quem não está escrevendo o código.

E decida cedo o que acontece quando a tela está desligada ou o celular está bloqueado, porque a resposta depende da versão do Android e de um ajuste do aparelho em vez de depender só do seu código. A página da tela desligada a toma versão por versão.

Perguntas frequentes

O aplicativo tem de estar aberto para a emulação funcionar?

Não. Um toque inicia o serviço se ele ainda não estiver rodando, e a troca acontece em segundo plano sem nenhuma tela sua.

A emulação de cartão pelo host consegue emular um cartão MIFARE Classic?

Não. O Android emula ISO-DEP e processa comandos da ISO/IEC 7816-4, e os esquemas cuja segurança fica abaixo dessa camada ficam fora de alcance.

Por que processCommandApdu é chamado na linha de execução principal?

Porque o leitor espera uma resposta. Devolva null quando a resposta der trabalho, e a envie depois com sendResponseApdu a partir de outra linha.

O que onDeactivated quer dizer?

Ou o leitor selecionou um identificador que resolve para outro serviço, ou o enlace de rádio se rompeu. O argumento diz qual dos dois.