Integrate reCAPTCHA Enterprise with Android apps

Stay organized with collections Save and categorize content based on your preferences.

This page explains how to integrate reCAPTCHA Enterprise in your Android app. Due to the variation in mobile devices in terms of screen size, performance, and UIs of the apps, the visual checkbox reCAPTCHA challenge (I'm not a robot) is not available for mobile apps. You can instead implement your own tiered enforcement strategy, such as an MFA flow to provide an alternative redemption path for suspicious traffic.

Before you begin

  1. Choose the best method for setting up reCAPTCHA Enterprise in your environment and complete the setup.

  2. Create a reCAPTCHA Key for the Android app platform.

Prepare your environment

  1. Prepare your development environment by downloading and installing the latest version of Android Studio.

  2. Ensure that you have an app with the minimum Android SDK value set to API 23: Android 6.0 (Marshmallow). You can either set the minimum SDK of your app to API 23 or create a new mobile app.

  3. If you are creating a new mobile app, create a test application by starting a new Android Studio project:

    1. Select Empty Activity. If you want to use Jetpack Compose on your app choose Empty Compose Activity.
    2. Set the language to kotlin.
    3. Set the minimum SDK value to API 23: Android 6.0 (Marshmallow).
  4. Ensure that Google's Maven repository google() is in the list of repositories in the project-level build.gradle file as shown in the following snippet:

    allprojects {
        repositories {
            google()
        }
    }
    

    For more information, see Google's Maven repository.

  5. To add the reCAPTCHA Enterprise API dependency, add the following build rule to the dependencies section of your app-level build.gradle file.

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

    For more information about adding dependencies in Android apps, see Add build dependencies.

  6. Add internet permission between the first <manifest> tag and the first <application> tag in your application's manifest (for example, AndroidManifest.xml). This permission is required because the reCAPTCHA Enterprise API involves network operations.

    <manifest ...>
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application ...>
        ...
      </application>
    </manifest>
    
  7. If you want to use AndroidX libraries in your new project, compile the SDK to Android 9.0 or higher and add the following code snippet to your gradle.properties.

    android.useAndroidX=true
    android.enableJetifier=true
    

    For more information, see Migrating to AndroidX.

Integrate reCAPTCHA Enterprise with your Android app

  1. Instantiate a client by using the SITE_KEY that you created for your Android app.

    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, "YOUR_SITE_KEY")
              .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(), "YOUR_SITE_KEY")
          .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. For each action of your app that is protected using reCAPTCHA Enterprise, call the execute method passing a RecaptchaAction. reCAPTCHA Enterprise provides a built-in set of actions and if necessary you can create custom actions.

    The following code snippet shows how to use execute to protect a LOGIN action.

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

The following sample code snippet shows a full integration of getClient(), and execute() methods on a single Activity app:

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, "YOUR_SITE_KEY")
        .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(), "YOUR_SITE_KEY")
      .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
            }
          });
  }
}

Handle communication errors

If your app cannot communicate with the reCAPTCHA service successfully, it might be because the API encountered an error. You must add logic in your app to gracefully handle such errors.

For more details about mitigations for common API errors, see RecaptchaErrorCode.

API reference

For a complete reference of the reCAPTCHA API for Android, see com.google.android.recaptcha.

What's next