API Account Transfer

Os usuários podem copiar Contas do Google e dados de um dispositivo Android existente para um novo usando o recurso Toque e pronto. Use a API Account Transfer para permitir que os usuários também copiem credenciais de contas personalizadas implementadas usando AbstractAccountAuthenticator e integradas com AccountManager. O sistema invoca a API Account Transfer do assistente de configuração do Toque e pronto em execução no novo dispositivo. O sistema também invoca a API Account Transfer para transferir dados de um smartphone Android para o Pixel usando um cabo.

Tela de boas-vindas do "Toque e pronto". Tela do "Toque e pronto" para selecionar uma fonte de dados.

Figura 1. A API Account Transfer é invocada pelo assistente de configuração do Toque e pronto em execução no novo dispositivo.

Para adicionar suporte à transferência de contas personalizadas, integre a API Account Transfer ao app. O Google Play Services pode estabelecer um canal criptografado bidirecional entre o dispositivo existente, também conhecido como dispositivo de origem, e o novo dispositivo, também conhecido como dispositivo de destino, para transferir dados da conta, conforme ilustrado na Figura 2. O canal criptografado não depende de conexão com servidores de terceiros para concluir a transferência.

Considere estes requisitos ao integrar a API Account Transfer ao seu app:

  • O dispositivo de origem precisa ter o Android 4.0.1 (API nível 14) ou versão mais recente.
  • O dispositivo de destino precisa ter o Android 8.0 (API nível 26) ou versão mais recente.
  • Os dispositivos de origem e de destino precisam ter a versão 11.2.0 ou mais recente do Google Play Services.
  • Você precisa criar seu app usando o SDK do Google Play Services versão 11.2.0 ou mais recente.

Ilustração da transferência da conta do dispositivo de origem para o dispositivo de destino.

Figura 2. A transferência ocorre em um canal criptografado que o Google Play Services estabelece entre os dispositivos de origem e de destino.

Adicionar a API Account Transfer ao seu projeto

Para usar a API Account Transfer no seu projeto, é necessário começar pela configuração do projeto com o SDK do Google Play Services. Para instruções detalhadas sobre como configurar o SDK do Google Play Services, consulte Configurar o Google Play Services.

Se você quiser compilar seletivamente a API Account Transfer do Google no app, adicione a seguinte regra de build ao bloco dependencies no arquivo build.gradle dentro do diretório do módulo do aplicativo:

Groovy

plugins {
  id 'com.android.application'
}
...
dependencies {
    // VERSION_NUMBER must be equal to or higher than 11.2.0.
    implementation 'com.google.android.gms:play-services-auth:<VERSION_NUMBER>'
}

Kotlin

plugins {
    id("com.android.application")
}
...
dependencies {
    // VERSION_NUMBER must be equal to or higher than 11.2.0.
    implementation("com.google.android.gms:play-services-auth:<VERSION_NUMBER>")
}

Para adicionar compatibilidade com a transferência de contas personalizadas, é necessário declarar o broadcast receiver START_ACCOUNT_EXPORT para seu serviço de autenticador no manifesto do app:

<receiver android:name=".MyBroadcastReceiver"  android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.START_ACCOUNT_EXPORT"/>
        ...
    </intent-filter>
</receiver>

Se o app não estiver instalado em uma imagem de sistema OEM e você não planejar colocá-lo em uma imagem de sistema OEM, faça o registro para ouvir a transmissão ACTION_START_ACCOUNT_EXPORT no dispositivo de origem para exportar os dados da conta, conforme descrito acima.

Se você instalar seu app em uma imagem de sistema OEM, também vai ser necessário fazer o registro para estas transmissões:

Transferir os dados da conta

Depois que um usuário optar por restaurar o conteúdo do dispositivo existente, o sistema vai enviar a transmissão ACTION_START_ACCOUNT_EXPORT aos pacotes associados às contas relevantes no dispositivo de origem.

Enviar os dados da conta

Para enviar dados da conta, inicie um serviço de autenticador no dispositivo de origem e chame sendData() depois que o serviço receber a transmissão ACTION_START_ACCOUNT_EXPORT. Você pode extrair uma referência a um objeto AccountTransferClient chamando getAccountTransferClient(Context) ou getAccountTransferClient(Activity). O snippet de código abaixo ilustra como enviar dados do dispositivo de origem:

Kotlin

val client: AccountTransferClient = AccountTransfer.getAccountTransferClient(this)
val exportTask: Task<Void> = client.sendData(ACCOUNT_TYPE, transferBytes)
try {
    // Wait for the task to either complete or provide the callback.
    Tasks.await(exportTask, TIMEOUT_API, TIME_UNIT)
} catch (e: Exception) {
    when(e) {
        is ExecutionException, is InterruptedException, is TimeoutException -> {
            client.notifyCompletion(ACCOUNT_TYPE,
                    AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE)
            return
        }
        else -> throw e
    }
}

Java

AccountTransferClient client = AccountTransfer.getAccountTransferClient(this);
Task<Void> exportTask = client.sendData(ACCOUNT_TYPE, transferBytes);
try {
  // Wait for the task to either complete or provide the callback.
  Tasks.await(exportTask, TIMEOUT_API, TIME_UNIT);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
  client.notifyCompletion(ACCOUNT_TYPE,AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE);
  return;
}

O assistente de configuração do dispositivo de destino recebe os dados da conta.

Receber os dados da conta

Se o mesmo serviço de autenticador estiver instalado neste dispositivo e tiver registrado interesse detectando a transmissão ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE, o dispositivo de destino enviará a transmissão ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE para os pacotes correspondentes.

Ao receber a transmissão ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE, inicie um serviço e chame retrieveData() no dispositivo de destino para extrair os dados enviados do dispositivo de origem. O snippet de código abaixo ilustra como extrair dados no dispositivo de destino:

Kotlin

val client: AccountTransferClient = AccountTransfer.getAccountTransferClient(this)
val transportTask: Task<Void> = client.retrieveData(ACCOUNT_TYPE)
try {
    val transferBytes: ByteArray = Tasks.await(transferTask, TIMEOUT_API, TIME_UNIT)
    // Add the transferred account(s) to AccountManager to register with the framework.
} catch (e: Exception) {
    when(e) {
        is ExecutionException, is InterruptedException, is TimeoutException -> {
            client.notifyCompletion(ACCOUNT_TYPE,
                    AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE)
            return
        }
        else -> throw e
    }
 }
client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_SUCCESS)

Java

AccountTransferClient client = AccountTransfer.getAccountTransferClient(this);
Task<Void> transferTask = client.retrieveData(ACCOUNT_TYPE);
try {
  byte[] transferBytes = Tasks.await(transferTask, TIMEOUT_API, TIME_UNIT);
  // Add the transferred account(s) to AccountManager to register with the framework.
} catch (ExecutionException | InterruptedException | TimeoutException e) {
  client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_FAILURE);
  return;
}
client.notifyCompletion(ACCOUNT_TYPE, AuthenticatorTransferCompletionStatus.COMPLETED_SUCCESS);

Concluir a transferência

Se necessário, o serviço de autenticador no dispositivo de destino também pode transferir dados de volta para o dispositivo de origem chamando sendData().

Para receber dados no dispositivo de origem, o serviço de autenticador precisa detectar a transmissão ACTION_ACCOUNT_EXPORT_DATA_AVAILABLE. De maneira semelhante, o serviço de autenticador no dispositivo de origem pode enviar outras mensagens para o dispositivo de destino.

Quando a transferência for concluída, o serviço de autenticador precisará chamar notifyCompletion() com o status de conclusão correto.

Se você precisa de mais segurança, é possível introduzir um desafio para o usuário nos dispositivos de origem ou de destino. Primeiro, confira se os desafios podem ser mostrados chamando getDeviceMetaData() e inspecionando o resultado. Se o serviço de autenticador no dispositivo de destino oferecer suporte a desafios, chame showUserChallenge() para mostrar o desafio.

Se o serviço de autenticador exigido não estiver instalado no dispositivo de destino no momento da transferência, o sistema armazenará os dados transferidos no armazenamento local temporário. Quando o app for instalado e aberto pela primeira vez, ele poderá chamar retrieveData() para verificar se há dados disponíveis no armazenamento local temporário. Se houver dados disponíveis, a API Account Transfer os retornará, caso contrário, a chamada falhará. Se não houver dados disponíveis no armazenamento local temporário, qualquer outra tentativa de recuperar dados falhará. Não chame notifyCompletion(), porque ele pode falhar.

Ilustração do dispositivo de destino que armazena os dados transferidos no
      armazenamento local temporário.

Figura 3. Se o serviço de autenticador exigido não estiver instalado no dispositivo de destino, o sistema armazenará os dados transferidos no armazenamento local temporário.

Testar a transferência de conta

O assistente de configuração é executado quando você configura um novo dispositivo. Redefinir um dispositivo para a configuração original regularmente para testar a configuração e a transferência de uma conta seria cansativo e demorado. Em vez disso, execute um subconjunto do fluxo do assistente de configuração para testar a transferência de uma conta de usuário de um dispositivo para outro.

Confira se há pelo menos uma conta personalizada no dispositivo de origem antes de iniciar o teste. Verifique também se o dispositivo de destino não está conectado a nenhuma conta personalizada. Se o dispositivo de destino já estiver conectado a uma conta personalizada quando você executar o assistente de configuração, não será possível adicionar essa conta quando o sistema chamar o método AccountManager.addAccountExplicitly().

Para fins de teste, é necessário usar um dispositivo com o Android 8.0 (nível 26 da API) ou mais recente como o dispositivo de destino.

É possível usar um dispositivo com o Android 4.0.1 (nível 14 da API) ou mais recente, e com o Google Play Services versão 11.2.0 ou mais recente, como o dispositivo de origem. Para criar o APK que você está testando, é necessário usar o SDK do Google Play Services versão 11.2.0 ou mais recente.

Para testar o fluxo do assistente de configuração, execute o comando abaixo no dispositivo de destino:

$ adb shell am start -a android.intent.action.MAIN -n com.google.android.gms/.smartdevice.d2d.ui.TargetActivity

O comando inicia uma atividade e mostra o assistente de configuração, pronto para parear o dispositivo de teste com outro dispositivo. Depois que os dispositivos estabelecerem uma conexão, você pode iniciar o processo de transferência da conta.