API Account Transfer

Os usuários podem copiar Contas do Google e dados de um dispositivo Android existente para um novo dispositivo Android usando o Toque e pronto. Use a API Account Transfer para permitir que os usuários também copiem credenciais de contas personalizadas implementadas por meio de 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 Tela do

Figura 2. A API Account Transfer é invocada a partir do assistente de configuração do "Toque e pronto" em execução no novo dispositivo.

Para adicionar compatibilidade com a transferência de contas personalizadas, integre a API Account Transfer ao seu app. O Google Play Services pode estabelecer um canal criptografado bidirecional entre o dispositivo existente, conhecido também como dispositivo de origem e o novo dispositivo, ou 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 os seguintes 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 posterior.
  • O dispositivo de destino precisa ter o Android 8.0 (API nível 26) ou versão posterior.
  • Os dispositivos de origem e de destino precisam ter a versão 11.2.0 ou posterior do Google Play Services.
  • Você precisa criar seu APK usando o SDK do Google Play Services versão 11.2.0 ou posterior.

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 ver instruções detalhadas sobre como configurar o SDK do Google Play Services, consulte Configurar o Google Play Services.

Se você quiser compilar a API Account Transfer do Google de forma seletiva no seu app, adicione a seguinte regra de compilação ao arquivo build.gradle dentro do diretório do módulo do aplicativo no bloqueio dependencies:

apply plugin: 'com.android.application'
        ...

        dependencies {
            // VERSION_NUMBER must be equal to or higher than 11.2.0.
            compile '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 seu app não estiver instalado em uma imagem de sistema OEM e você não quiser colocar o app nesse tipo de imagem no futuro, registre-se 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 será necessário se registrar para as seguintes transmissões:

Transferir os dados da conta

Depois que um usuário escolhe restaurar o conteúdo do dispositivo existente, o sistema envia 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 conseguir uma referência a um objeto AccountTransferClient chamando getAccountTransferClient(Context) ou getAccountTransferClient(Activity). O snippet de código a seguir ilustra como enviar dados a partir 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 ouvindo 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 recuperar os dados enviados do dispositivo de origem. O snippet de código a seguir ilustra como recuperar 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 it 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 it 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 ouvir a transmissão ACTION_ACCOUNT_EXPORT_DATA_AVAILABLE. Da 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ê precisar de mais segurança, será possível introduzir um desafio para o usuário nos dispositivos de origem ou de destino. Primeiro, é necessário verificar se os desafios são exibidos chamando getDeviceMetaData() e analisando o resultado. Se o serviço de autenticador no dispositivo de destino for compatível com desafios, você poderá chamar showUserChallenge() para exibir 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 é instalado e aberto pela primeira vez, ele pode 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á, ou então 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 pode haver falha.

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

Figura 2. 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. A redefinição regular de um dispositivo para a configuração original com o objetivo de testar a configuração e a transferência da conta é cansativa e demorada. 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.

Verifique 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 (API nível 26) ou posterior como dispositivo de destino.

É possível usar um dispositivo com o Android 4.0.1 (API nível 14) ou versão posterior, bem como o Google Play Services versão 11.2.0 ou posterior, 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 posterior.

Para testar o fluxo do assistente de configuração, execute o seguinte comando 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 exibe o assistente de configuração, pronto para parear o dispositivo de teste com outro dispositivo. Depois que os dispositivos estabelecerem uma conexão, será possível iniciar o processo de transferência da conta.