API de transferencia de cuentas

Los usuarios pueden copiar datos y Cuentas de Google desde un dispositivo existente con Android a un dispositivo nuevo con Android gracias a Tap & Go. Usa la API de Account Transfer para permitir que los usuarios también copien las credenciales de cuentas personalizadas que se implementaron con AbstractAccountAuthenticator y se integraron con AccountManager. El sistema invoca la API de Account Transfer del asistente de configuración de Tap & Go que se ejecuta en el dispositivo nuevo. El sistema también invoca la API de Account Transfer para transferir datos de un teléfono Android a un Pixel con un cable.

Pantalla de bienvenida de Tap & Go Pantalla de Tap & Go para seleccionar una fuente de datos

Figura 1: La API de Account Transfer se invoca desde el asistente de configuración de Tap & Go que se ejecuta en un dispositivo nuevo.

Para agregar compatibilidad con la transferencia de cuentas personalizadas, integra la API de Account Transfer en tu app. Luego, los Servicios de Google Play pueden establecer un canal encriptado bidireccional entre el dispositivo existente, también conocido como dispositivo fuente, y el dispositivo nuevo, también conocido como dispositivo objetivo, para transferir datos de la cuenta, como se ilustra en la Figura 2. El canal encriptado no depende de una conexión a servidores de terceros para completar la transferencia.

Ten en cuenta los siguientes requisitos cuando integres la API de Account Transfer en tu app:

  • El dispositivo de origen debe ejecutar Android 4.0.1 (nivel de API 14) o una versión posterior.
  • El dispositivo de destino debe ejecutar Android 8.0 (nivel de API 26) o una versión posterior.
  • Tanto los dispositivos de origen como los de destino deben ejecutar la versión 11.2.0 o una posterior de los Servicios de Google Play.
  • Debes compilar tu app con la versión 11.2.0 o una posterior del SDK de los Servicios de Google Play.

Ilustración de transferencia de cuenta del dispositivo de origen al de destino

Figura 2: La transferencia se realiza a través de un canal encriptado que los Servicios de Google Play establecen entre los dispositivos de origen y de destino.

Cómo agregar la API de Account Transfer a tu proyecto

Si deseas usar la API de Account Transfer en tu proyecto, primero debes configurar el proyecto con el SDK de los Servicios de Google Play. Para obtener instrucciones detalladas sobre cómo configurar el SDK de Servicios de Google Play, consulta Cómo configurar los Servicios de Google Play.

Si deseas compilar de forma selectiva la API de Account Transfer de Google en tu app, agrega la siguiente regla de compilación al bloque dependencies del archivo build.gradle en el directorio del módulo de tu aplicación:

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>")
}

Si quieres admitir la transferencia de cuentas personalizadas, debes declarar el receptor de emisión START_ACCOUNT_EXPORT para tu servicio de autenticación en el manifiesto de tu app:

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

Si tu app no está instalada en una imagen del sistema OEM y no tienes pensado hacerlo, asegúrate de registrarte para escuchar la transmisión de ACTION_START_ACCOUNT_EXPORT en el dispositivo de origen para exportar los datos de la cuenta como se describió con anterioridad.

Si instalas tu app en una imagen del sistema OEM, también debes registrarte para las siguientes transmisiones:

Cómo transferir los datos de la cuenta

Después de que un usuario decide restablecer el contenido de su dispositivo existente, el sistema envía la transmisión ACTION_START_ACCOUNT_EXPORT a los paquetes asociados con las cuentas relevantes en el dispositivo de origen.

Cómo enviar los datos de la cuenta

Para enviar datos de la cuenta, inicia un servicio autenticador en el dispositivo de origen y llama a sendData() después de que el servicio reciba la transmisión de ACTION_START_ACCOUNT_EXPORT. Obtienes la referencia a un objeto AccountTransferClient llamando a getAccountTransferClient(Context) o getAccountTransferClient(Activity). En el siguiente fragmento de código, se muestra cómo enviar datos desde el dispositivo fuente:

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;
}

El asistente de configuración del dispositivo de destino recibe los datos de la cuenta.

Cómo recibir los datos de la cuenta

Si el mismo servicio autenticador está instalado en este dispositivo y se registra su interés escuchando la transmisión de ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE, el dispositivo de destino envía la transmisión de ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE a los paquetes correspondientes.

Cuando recibas la transmisión de ACTION_ACCOUNT_IMPORT_DATA_AVAILABLE, inicia un servicio y llama a retrieveData() en el dispositivo de destino para recuperar los datos enviados desde el dispositivo de origen. En el siguiente fragmento de código, se muestra cómo recuperar datos en el 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);

Cómo finalizar la transferencia

Si es necesario, el servicio autenticador en el dispositivo de destino también puede transferir datos al dispositivo de origen llamando a sendData().

Para recibir datos en el dispositivo de origen, tu servicio autenticador debe escuchar la transmisión de ACTION_ACCOUNT_EXPORT_DATA_AVAILABLE. De manera similar, el servicio autenticador en el dispositivo de origen puede enviar más mensajes al dispositivo de destino.

Cuando finaliza la transferencia, tu servicio autenticador debe llamar a notifyCompletion() con el estado de finalización apropiado.

Si necesitas más seguridad, puedes presentar un desafío para el usuario en el dispositivo de origen o de destino. Primero, verifica si se pueden mostrar los desafíos llamando a getDeviceMetaData() y, luego, inspeccionando el resultado. Si el servicio autenticador del dispositivo de destino admite desafíos, llama a showUserChallenge() para mostrarlo.

Si el servicio autenticador requerido no está instalado en el dispositivo de destino en el momento de la transferencia, el sistema almacenará los datos transferidos en el almacenamiento local temporal. Cuando la app se instala y se abre por primera vez, puede llamar a retrieveData() para comprobar si hay datos disponibles en el almacenamiento local temporal. Si hay datos disponibles, la API de Account Transfer muestra los datos; de lo contrario, la llamada falla. Si no hay datos disponibles en el almacenamiento local temporal, es posible que fallen los intentos de recuperación de datos. No llames a notifyCompletion(), ya que puede fallar.

Ilustración del dispositivo de destino que guarda los datos transferidos en el almacenamiento local temporal

Figura 3: Si el servicio autenticador requerido no está instalado en el dispositivo de destino, el sistema guardará los datos transferidos en el almacenamiento local temporal.

Cómo probar la transferencia de cuentas

El asistente de configuración se ejecuta cuando configuras un dispositivo nuevo. El restablecimiento frecuente de la configuración de fábrica de un dispositivo para probar la configuración y la transferencia de una cuenta sería tedioso y requeriría mucho tiempo. En su lugar, puedes ejecutar un subconjunto del flujo del asistente de configuración para probar la transferencia de la cuenta de un usuario de un dispositivo a otro.

Asegúrate de tener al menos una cuenta personalizada en tu dispositivo de origen antes de iniciar la prueba. Además, asegúrate de que el dispositivo de destino no haya accedido a ninguna cuenta personalizada. Si el dispositivo de destino ya accedió a una cuenta personalizada cuando ejecutas el asistente de configuración, el intento de agregar la misma cuenta falla cuando el sistema llama al método AccountManager.addAccountExplicitly().

Para realizar pruebas, debes usar un dispositivo con Android 8.0 (nivel de API 26) o versiones posteriores como dispositivo de destino.

Puedes usar un dispositivo con Android 4.0.1 (nivel de API 14) o versiones posteriores, así como con la versión 11.2.0 o una posterior de Servicios de Google Play como dispositivo de origen. Para compilar el APK que estás probando, debes usar la versión 11.2.0 o una posterior del SDK de Servicios de Google Play.

Para probar el flujo del asistente de configuración, ejecuta el siguiente comando en tu dispositivo de destino:

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

El comando inicia una actividad y muestra el asistente de configuración, listo para vincular el dispositivo de prueba con otro. Cuando los dispositivos establecen una conexión, puedes iniciar el proceso de transferencia de cuentas.