Até agora, falamos sobre o acesso às APIs Google, que usam contas e usuários definidos pelo Google. No entanto, se você tiver seu próprio serviço on-line, ele não terá usuários nem Contas do Google. Então, o que você precisa fazer? É relativamente simples instalar novos tipos de conta no dispositivo de um usuário. Esta lição explica como criar um tipo de conta personalizada que funciona da mesma forma que as contas integradas.
Implementar seu código de conta personalizado
Primeiramente, você precisará de uma forma de receber credenciais do usuário. Pode ser algo simples, como uma caixa de diálogo que solicita um nome e uma senha. Ou pode ser um procedimento mais diferenciado, como uma senha única ou verificação biométrica. De qualquer forma, é sua responsabilidade implementar o código que:
- coleta as credenciais do usuário.
- autentica as credenciais com o servidor;
- armazena as credenciais no dispositivo,
Normalmente, uma única atividade pode lidar com esses três requisitos. Chamaremos isso de atividade do autenticador.
Como as atividades do autenticador precisam interagir com o sistema do AccountManager
, elas têm certos requisitos que as atividades normais não têm. Para que seja mais fácil acertar tudo, o framework do Android fornece uma classe base, AccountAuthenticatorActivity
, que você pode estender para criar seu próprio autenticador personalizado.
O modo como você aborda os dois primeiros requisitos de uma atividade do autenticador, coleta e autenticação de credenciais, depende totalmente de você. Se houvesse apenas uma maneira de fazer isso, não haveria necessidade de tipos de conta "personalizados". O terceiro requisito tem uma implementação canônica e bastante simples:
Kotlin
Account(username, your_account_type).also { account -> accountManager.addAccountExplicitly(account, password, null) }
Java
final Account account = new Account(username, your_account_type); accountManager.addAccountExplicitly(account, password, null);
Segurança inteligente
É importante compreender que o AccountManager
não é um serviço de criptografia nem um keychain. Ele armazena as credenciais da conta na forma como elas são transmitidas, em texto simples. Na maioria dos dispositivos, essa não é uma preocupação específica, já que o armazenamento é feito em um banco de dados que só pode ser acessado pela raiz. No entanto, em um dispositivo com acesso root, as credenciais poderiam ser lidas por qualquer pessoa com acesso adb
ao dispositivo.
Com base nessas informações, não transmita a senha atual do usuário para AccountManager.addAccountExplicitly()
. Em vez disso, armazene um token criptograficamente seguro que seria de uso limitado para um invasor. Se suas credenciais de usuário estiverem protegendo algo valioso, considere fazer algo semelhante.
Lembre-se: para o código de segurança, siga a regra do programa "Os Caçadores de Mitos" e não tente fazer isso em casa. Consulte um profissional de segurança antes de implementar qualquer código de conta personalizado.
Agora que já tratamos das exoneração de responsabilidade sobre segurança, é hora de voltar ao trabalho. Você já implementou a parte principal do código da sua conta personalizada, o restante é bem simples.
Estender o AbstractAccountAuthenticator
Para que o AccountManager
funcione com seu código de conta personalizado, você precisa de uma classe que implemente as interfaces que o AccountManager
espera.
Essa classe é a de autenticador.
A maneira mais fácil de criar uma classe de autenticador é estender AbstractAccountAuthenticator
e implementar os métodos abstratos dele. Se você já concluiu as lições anteriores, os métodos abstratos de AbstractAccountAuthenticator
parecerão familiares: eles são o oposto dos métodos que você chamou na lição anterior para receber informações da conta e tokens de autorização.
A implementação correta de uma classe de autenticador requer diversas partes diferentes do código. Primeiro, o AbstractAccountAuthenticator
tem sete métodos abstratos que você precisará modificar. Em segundo lugar, você precisa adicionar um filtro de intent para "android.accounts.AccountAuthenticator"
ao manifesto do app (mostrado na próxima seção). Por fim, forneça dois recursos XML que definem, entre outras coisas, o nome do seu tipo de conta personalizada e o ícone que o sistema exibirá ao lado de contas desse tipo.
Você encontrará um guia passo a passo para implementar uma classe de autenticador e os arquivos XML na documentação do AbstractAccountAuthenticator
. Há também uma implementação de exemplo no app de amostra SampleSyncAdapter.
Ao ler o código de SampleSyncAdapter, você perceberá que vários dos métodos retornam um intent em um pacote. Essa é a mesma intent que será usada para iniciar sua atividade de autenticador personalizado. Se a atividade do autenticador precisar de quaisquer parâmetros especiais de inicialização, você poderá anexá-los à intent usando Intent.putExtra()
.
Criar um serviço de autenticador
Agora que você tem uma classe de autenticador, precisa de um lugar para ela funcionar.
Autenticadores de conta precisam estar disponíveis para vários aplicativos e funcionar em segundo plano, então é necessário que sejam executados dentro de um Service
. Chamaremos isso de serviço de autenticador.
Seu serviço de autenticador pode ser muito simples. Tudo o que ele precisa fazer é criar uma instância da sua classe de autenticador em onCreate()
e chamar getIBinder()
em onBind()
. O SampleSyncAdapter contém um bom exemplo de um serviço de autenticador.
Lembre-se de adicionar uma tag <service>
ao arquivo de manifesto e adicionar um filtro de intent para o intent AccountAuthenticator e declarar o autenticador da conta:
<service ...> <intent-filter> <action android:name="android.accounts.AccountAuthenticator" /> </intent-filter> <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> </service>
Distribuir o serviço
Pronto! Agora, o sistema reconhece seu tipo de conta, junto a todos os tipos de conta conhecidos, como "Google" e "Corporativa". Você pode usar a página de configurações Contas e sincronização para adicionar uma conta, e os apps que pedirem contas do seu tipo personalizado poderão enumerar e autenticar assim como fariam com qualquer outro tipo de conta.
É claro que tudo isso pressupõe que o serviço da sua conta esteja instalado no dispositivo. Se apenas um aplicativo acessa o serviço, isso não tem muita relevância. Basta agrupar o serviço no app. No entanto, se você quer que seu serviço de conta seja usado por mais de um app, é um pouco mais complicado. Não é recomendável agrupar o serviço com todos os apps e ter várias cópias dele ocupando espaço no dispositivo do usuário.
Uma solução seria colocar o serviço em um APK pequeno para fins especiais. Quando um app quiser usar o tipo de conta personalizada, ele poderá verificar se o serviço da conta personalizada está disponível. Caso contrário, ele poderá direcionar o usuário para o Google Play para fazer o download do serviço. Isso pode parecer complicado no início, mas é muito fácil em comparação com a alternativa de inserir novamente as credenciais para cada app que usa sua conta personalizada.