Crea cuentas nuevas con un solo toque

Si admites el acceso con Cuentas de Google, puedes usar el cliente de acceso con One Tap para brindarles a los usuarios una experiencia de creación de cuentas sin inconvenientes que nunca los quite del contexto de tu app.

IU de registro con One Tap

Cuando muestras la IU de One Tap, se les solicita a los usuarios que creen una cuenta nueva con tu app mediante una de las Cuentas de Google en su dispositivo. Si el usuario decide continuar, obtendrás un token de ID con información básica de perfil (su nombre, foto de perfil y dirección de correo electrónico verificada) que puedes usar para crear la cuenta nueva.

La implementación de la creación de cuentas con One Tap consta de dos partes:

  • Cómo integrar el cliente de One Tap a tu app, como se describe en esta página Esto es casi lo mismo que usar el acceso con One Tap, pero con algunas diferencias en la configuración.
  • Agregar a tu backend la capacidad de crear cuentas de usuario a partir de tokens de ID de Google, que se analiza en Usa tokens de ID en el backend.

¿Dónde debo usar el registro con One Tap?

El lugar de mayor impacto para ofrecer el registro con One Tap a los usuarios es en un contexto en el que el acceso habilita nuevas funciones. Primero, intenta hacer que el usuario acceda con una credencial guardada. Si no se encuentran credenciales guardadas, ofrece crear una cuenta nueva para el usuario.

Antes de comenzar

Configura el proyecto de la Consola de APIs de Google y el de Android como se describe en Cómo comenzar a acceder con One Tap.

1. Cómo configurar el cliente One Tap

Para configurar el cliente One Tap para la creación de cuentas, haz lo siguiente:

  • No habilitar las solicitudes de credenciales de contraseña. (El registro con un toque solo es posible con la autenticación basada en tokens).
  • Habilita las solicitudes de token de ID de Google mediante setGoogleIdTokenRequestOptions() y esta configuración:

Java

public class YourActivity extends AppCompatActivity {

  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signUpRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signUpRequest = BeginSignInRequest.builder()
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.your_web_client_id))
                      // Show all accounts on the device.
                      .setFilterByAuthorizedAccounts(false)
                      .build())
              .build();

      // ...
  }
}

Kotlin

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signUpRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signUpRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Show all accounts on the device.
                    .setFilterByAuthorizedAccounts(false)
                    .build())
            .build()
        // ...
    }
    // ...
}

2. Realiza un seguimiento de la cancelación de la IU de One Tap

Debes realizar un seguimiento para saber si el usuario ya rechazó usar el registro con One Tap. Para ello, cierra el mensaje o presiona fuera de él. Esto puede ser tan simple como una propiedad booleana de tu actividad. (Consulta Cómo dejar de mostrar la IU de One Tap a continuación).

3. Muestra la IU de registro con One Tap

Si el usuario no rechazó usar One Tap para crear una cuenta nueva, llama al método beginSignIn() del objeto del cliente y adjunta objetos de escucha al Task que muestra. Por lo general, las apps realizan este paso cuando una solicitud de acceso con One Tap no encuentra ninguna credencial guardada, es decir, en el objeto de escucha de fallas de la solicitud de acceso.

El cliente de One Tap llamará al objeto de escucha que detecta el resultado correcto si el usuario tiene una o más Cuentas de Google configuradas en el dispositivo. En el objeto de escucha que detecta el resultado correcto, obtén el intent pendiente del resultado de Task y pásalo a startIntentSenderForResult() para iniciar la IU de One Tap.

Si el usuario no tiene ninguna Cuenta de Google en el dispositivo, el cliente de One Tap llamará al objeto de escucha de fallas. En este caso, no es necesario que realices ninguna acción: solo puedes continuar presentando la experiencia de salir de tu cuenta en la app, y el usuario puede registrarse con tu flujo normal de creación de cuentas.

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No Google Accounts found. Just continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Kotlin

oneTapClient.beginSignIn(signUpRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No Google Accounts found. Just continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. Cómo controlar la respuesta del usuario

La respuesta del usuario al mensaje de registro en One Tap se informará a tu app a través del método onActivityResult() de tu actividad. Si el usuario eligió crear una cuenta, el resultado será un token de ID de Google. Si el usuario se negó a registrarse, ya sea cerrando la IU de One Tap o presionando fuera de ella, el resultado mostrará el código RESULT_CANCELED. Tu app necesita manejar ambas posibilidades.

Crea una cuenta con un token de ID de Google

Si el usuario decidió registrarse con una Cuenta de Google, puedes obtener un token de ID para el usuario pasando los datos del intent de onActivityResult() al método getSignInCredentialFromIntent() del cliente de One Tap. La credencial tendrá una propiedad googleIdToken no nula.

Usa el token de ID para crear una cuenta en tu backend (consulta Autentica con un backend mediante tokens de ID) y haz que el usuario acceda.

La credencial también contiene cualquier detalle adicional que hayas solicitado, como el número de teléfono verificado de la cuenta, si está disponible.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
            }
        }
    }
    // ...
}

Cómo dejar de mostrar la IU de One Tap

Si el usuario rechazó el acceso, la llamada a getSignInCredentialFromIntent() arrojará una ApiException con un código de estado CommonStatusCodes.CANCELED. Cuando esto sucede, debes dejar de mostrar la IU de acceso con One Tap para no molestar a los usuarios con mensajes repetidos. En el siguiente ejemplo, para lograr esto, se debe configurar una propiedad en la actividad, que se usa para determinar si se le ofrece al usuario acceso con One Tap. Sin embargo, también puedes guardar un valor en SharedPreferences o usar otro método.

Es importante que implementes tu propio límite de frecuencia de los mensajes de acceso con One Tap. Si no lo haces y un usuario cancela varios mensajes seguidas, el cliente de One Tap no le solicitará permiso durante las siguientes 24 horas.

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

Próximos pasos

Cuando un usuario completa el flujo de registro con One Tap, obtienes un token de ID de Google, que incluye información básica del perfil: la dirección de correo electrónico del usuario, su nombre completo y la URL de la foto de perfil. En muchas apps, esta información es suficiente para autenticar al usuario en el backend y crear una cuenta nueva.

Si necesitas información adicional para completar la creación de la cuenta (por ejemplo, la fecha de nacimiento del usuario), muéstrale un flujo de detalles de registro, en el que solicitas esta información adicional. Luego, envíala a tu backend para completar la creación de la cuenta.