Integra reCAPTCHA en apps para Android

En esta página, se explica cómo integrar reCAPTCHA en tu app para Android.

Si quieres proporcionar desafíos visuales para el tráfico sospechoso, puedes usar la API de reCAPTCHA de SafetyNet.

Antes de comenzar

  1. Prepara tu entorno para reCAPTCHA.

  2. Crea una clave de reCAPTCHA para la plataforma de apps para Android.

    Como alternativa, puedes copiar el ID de una clave de reCAPTCHA existente para Android si realizas uno de los siguientes pasos:

    • Para copiar el ID de una clave existente desde la consola de Google Cloud, haz lo siguiente:

      1. Ve a la página reCAPTCHA.

        Ir a reCAPTCHA

      2. En la lista de claves de reCAPTCHA, mantén el puntero sobre la clave que deseas copiar y, luego, haz clic en .
    • Para copiar el ID de una clave existente con la API de REST, usa el método projects.keys.list.
    • Para copiar el ID de una clave existente con la gcloud CLI, usa el comando gcloud recaptcha keys list.

Prepara tu entorno de Android

Android nativo

  1. Prepara tu entorno de desarrollo. Para ello, descarga e instala la versión más reciente de Android Studio.

  2. Asegúrate de tener una app con el valor mínimo del SDK de Android establecido en API 19: Android 4.4 (KitKat). Puedes establecer el SDK mínimo de tu app en API 19 o crear una app para dispositivos móviles nueva.

  3. Si estás creando una nueva app para dispositivos móviles, crea una aplicación de prueba iniciando un nuevo proyecto de Android Studio:

    1. Selecciona Empty Activity. Si quieres usar Jetpack Compose en tu app, elige Actividad de Compose vacía.
    2. Configura el idioma en kotlin.
    3. Establece el valor mínimo del SDK en API 19: Android 4.4 (KitKat).
  4. Asegúrate de que el repositorio de Maven de Google google() esté en la lista de repositorios del archivo build.gradle de nivel de proyecto, como se muestra en el siguiente fragmento:

    allprojects {
        repositories {
            google()
        }
    }
    

    Para obtener más información, consulta el repositorio de Maven de Google.

  5. Para agregar la dependencia de la API de reCAPTCHA, agrega la siguiente regla de compilación a la sección dependencies de tu archivo build.gradle a nivel de la app.

      implementation 'com.google.android.recaptcha:recaptcha:18.5.1'
    

    Si quieres obtener más información para agregar dependencias en apps para Android, consulta Cómo agregar dependencias de compilación.

  6. Agrega un permiso de Internet entre la primera etiqueta <manifest> y la primera etiqueta <application> en el manifiesto de tu aplicación (por ejemplo, AndroidManifest.xml). Este permiso es obligatorio porque la API de reCAPTCHA implica operaciones de red.

    <manifest ...>
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application ...>
        ...
      </application>
    </manifest>
    
  7. Si quieres usar bibliotecas AndroidX en tu nuevo proyecto, compila el SDK en Android 9.0 o una versión posterior, y agrega el siguiente fragmento de código a tu gradle.properties.

    android.useAndroidX=true
    android.enableJetifier=true
    

    Para obtener más información, consulta Cómo migrar a AndroidX.

Flutter

Si deseas obtener instrucciones detalladas para usar reCAPTCHA a través de Flutter, consulta la documentación de Flutter.

ReactNative

Para obtener instrucciones detalladas sobre el uso de reCAPTCHA a través de React Native, consulta la documentación de React Native.

Integra reCAPTCHA en tu app para Android

  1. Crea una instancia de cliente con la clave de reCAPTCHA (KEY_ID) que creaste para tu app para Android.

    Kotlin

    class MainActivity : AppCompatActivity() {
    
        private lateinit var recaptchaClient: RecaptchaClient
    
        override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
          initializeRecaptchaClient()
          // ... rest of onCreate code
        }
    
        private fun initializeRecaptchaClient() {
          lifecycleScope.launch {
            Recaptcha.getClient(application, "KEY_ID")
              .onSuccess { client ->
                recaptchaClient = client
              }
              .onFailure { exception ->
                // Handle communication errors ...
                // See "Handle communication errors" section
              }
          }
        }
    
        // ... rest of activity code.
    }
    

    Java

    public final class MainActivity extends Activity {
      @Nullable private RecaptchaTasksClient recaptchaTasksClient = null;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initializeRecaptchaClient();
        // ... rest of onCreate code
      }
    
      private void initializeRecaptchaClient() {
        Recaptcha
          .getTasksClient(getApplication(), "KEY_ID")
          .addOnSuccessListener(
              this,
              new OnSuccessListener<RecaptchaTasksClient>() {
                @Override
                public void onSuccess(RecaptchaTasksClient client) {
                  MainActivity.this.recaptchaTasksClient = client;
                }
              })
          .addOnFailureListener(
              this,
              new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                  // Handle communication errors ...
                  // See "Handle communication errors" section
                }
              });
      }
    
      // ... rest of activity code.
    }
    
  2. Para cada acción de tu app que esté protegida con reCAPTCHA, llama al método execute pasando una RecaptchaAction. reCAPTCHA proporciona un conjunto integrado de acciones y, si es necesario, puedes crear acciones personalizadas.

    En el siguiente fragmento de código, se muestra cómo usar execute para proteger una acción LOGIN.

    Kotlin

    private fun executeLoginAction() {
      lifecycleScope.launch {
        recaptchaClient
          .execute(RecaptchaAction.LOGIN)
          .onSuccess { token ->
            // Handle success ...
            // See "What's next" section for instructions
            // about handling tokens.
          }
          .onFailure { exception ->
            // Handle communication errors ...
            // See "Handle communication errors" section
          }
      }
    }
    

    Java

    private void executeLoginAction(View v) {
      assert recaptchaTasksClient != null;
      recaptchaTasksClient
        .executeTask(RecaptchaAction.LOGIN)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<String>() {
              @Override
              public void onSuccess(String token) {
                // Handle success ...
                // See "What's next" section for instructions
                // about handling tokens.
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Handle communication errors ...
                // See "Handle communication errors" section
              }
            });
    }
    

En el siguiente fragmento de código de muestra, se muestra una integración completa de los métodos getClient() y execute() en una sola app de Activity:

Kotlin

class MainActivity : AppCompatActivity() {

  private lateinit var recaptchaClient: RecaptchaClient

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    initializeRecaptchaClient()
    findViewById<View>(R.id.btn_login).setOnClickListener { executeLoginAction() }
    findViewById<View>(R.id.btn_redeem).setOnClickListener { executeRedeemAction() }
  }

  private fun initializeRecaptchaClient() {
    lifecycleScope.launch {
      Recaptcha.getClient(application, "KEY_ID")
        .onSuccess { client ->
          recaptchaClient = client
        }
        .onFailure { exception ->
          // Handle communication errors ...
          // See "Handle communication errors" section
        }
    }
  }

  private fun executeLoginAction() {
    lifecycleScope.launch {
      recaptchaClient
        .execute(RecaptchaAction.LOGIN)
        .onSuccess { token ->
          // Handle success ...
          // See "What's next" section for instructions
          // about handling tokens.
        }
        .onFailure { exception ->
          // Handle communication errors ...
          // See "Handle communication errors" section
        }
    }
  }

  private fun executeRedeemAction(){
    lifecycleScope.launch {
      recaptchaClient
        .execute(RecaptchaAction.custom("redeem"))
        .onSuccess { token ->
          // Handle success ...
          // See "What's next" section for instructions
          // about handling tokens.
        }
        .onFailure { exception ->
          // Handle communication errors ...
          // See "Handle communication errors" section
        }
    }
  }
}

Java

public final class MainActivity extends Activity {
  @Nullable private RecaptchaTasksClient recaptchaTasksClient = null;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initializeRecaptchaClient();
    findViewById(R.id.btn_login).setOnClickListener(this::executeLoginAction);
    findViewById(R.id.btn_redeem).setOnClickListener(this::executeRedeemAction);
  }

  private void initializeRecaptchaClient() {
    Recaptcha
      .getTasksClient(getApplication(), "KEY_ID")
      .addOnSuccessListener(
          this,
          new OnSuccessListener<RecaptchaTasksClient>() {
            @Override
            public void onSuccess(RecaptchaTasksClient client) {
              MainActivity.this.recaptchaTasksClient = client;
            }
          })
      .addOnFailureListener(
          this,
          new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
          });
  }

  private void executeLoginAction(View v) {
    assert recaptchaTasksClient != null;
    recaptchaTasksClient
      .executeTask(RecaptchaAction.LOGIN)
      .addOnSuccessListener(
          this,
          new OnSuccessListener<String>() {
            @Override
            public void onSuccess(String token) {
              // Handle success ...
              // See "What's next" section for instructions
              // about handling tokens.
            }
          })
      .addOnFailureListener(
          this,
          new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
          });
  }

  private void executeRedeemAction(View v) {
    assert recaptchaTasksClient != null;
    recaptchaTasksClient
      .executeTask(RecaptchaAction.custom("redeem"))
      .addOnSuccessListener(
          this,
          new OnSuccessListener<String>() {
            @Override
            public void onSuccess(String token) {
              // Handle success ...
              // See "What's next" section for instructions
              // about handling tokens.
            }
          })
      .addOnFailureListener(
          this,
          new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
          });
  }
}

Establece un tiempo de espera para las llamadas a la API

Puedes especificar un valor de tiempo de espera para las APIs de getClient y execute con la propiedad timeout de cada API.

Se utiliza un tiempo de espera predeterminado de 10 segundos para getClient y de 10 segundos para las APIs de execute.

Kotlin

  • Establece el tiempo de espera cuando llames a getClient.

        lifecycleScope.launch {
          Recaptcha.getClient(application, "KEY_ID", timeout = 20000L)
            .onSuccess { client ->
              recaptchaClient = client
            }
            .onFailure { exception ->
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
        }
    

    Este fragmento de código establece el tiempo de espera de getClient en 20 segundos.

  • Establece el tiempo de espera cuando llames a execute.

        lifecycleScope.launch {
          recaptchaClient
            .execute(RecaptchaAction.LOGIN(), timeout = 10000L)
            .onSuccess { token ->
              // Handle success ...
              // See "What's next" section for instructions
              // about handling tokens.
            }
            .onFailure { exception ->
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
        }
    

    Este fragmento de código establece el tiempo de espera de execute en 10 segundos.

Java

  • Establece el tiempo de espera cuando llames a getClient.

      Recaptcha
        .getTasksClient(getApplication(), "KEY_ID", 20000L)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<RecaptchaTasksClient>() {
              @Override
              public void onSuccess(RecaptchaTasksClient client) {
                MainActivity.this.recaptchaTasksClient = client;
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Handle communication errors ...
                // See "Handle communication errors" section
              }
            });
    

    Este fragmento de código establece el tiempo de espera de getClient en 20 segundos.

  • Establece el tiempo de espera cuando llames a execute.

      recaptchaTasksClient
        .executeTask(RecaptchaAction.custom("redeem"), 10000L)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<String>() {
              @Override
              public void onSuccess(String token) {
                // Handle success ...
                // See "What's next" section for instructions
                // about handling tokens.
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Handle communication errors ...
                // See "Handle communication errors" section
              }
            });
    

    Este fragmento de código establece el tiempo de espera de execute en 10 segundos.

Maneja errores de comunicación

Si la app no puede comunicarse con el servicio de reCAPTCHA correctamente, es posible que se deba a que la API encontró un error. Debes agregar lógica en tu app para manejar correctamente esos errores.

Para obtener más detalles sobre las mitigaciones de errores comunes de la API, consulta RecaptchaErrorCode.

Referencia de la API

Para obtener una referencia completa de la API de reCAPTCHA para Android, consulta com.google.android.recaptcha.

¿Qué sigue?

  • Para evaluar el token de respuesta de reCAPTCHA, crea una evaluación.