Integrating reCAPTCHA Enterprise with Android apps

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 reCAPTCHA challenge (I'm not a robot) is not available for mobile apps. For an alternative friction method, see Configuring Multi-factor authentication (MFA).

Before you begin

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

  2. Android SDK is accessible after a security review. Contact our sales team to onboard your site to this feature.

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

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

Integrating reCAPTCHA Enterprise with your Android app

To integrate reCAPTCHA Enterprise with your Android app, do the following:

  1. Create a test application by starting a new Android Studio project. When creating the project, select Empty Activity, set the language to Java, and set the minimum SDK to API 16: Android 4.1 (Jelly Bean).

  2. 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.

  3. 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.gms:play-services-recaptcha:16.0.1'
    

    For more information about API dependencies in Android apps, see Set Up Google Play Services.

  4. 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>
    
  5. 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.

  6. In your app (MainActivity.java), invoke the reCAPTCHA Enterprise API by calling init(), execute(), and close() methods in the following sequence:

    1. Call init() when you start your app or the activity containing the action you want to protect.
    2. Call execute() after the action you want to protect is taken. For example, the login button is clicked. execute() then returns a RecaptchaResultData token.
    3. Call close() when there are no more actions to verify.

    When calling these three methods in your app, override the onSuccess() and onFailure() methods to handle both possible outcomes of the API calls. In particular, if the API passes an instance of ApiException into onFailure(), you must handle each possible status code that you can retrieve using getStatusCode(). For more information, see Handling communication errors.

The following sample code snippet shows how to invoke init(), execute(), and close() methods:

public final class MainActivity extends Activity {
   private RecaptchaHandle handle;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);

     // Step 1: Call init() once the activity starts.
     Recaptcha.getClient(this)
         .init("YOUR_SITE_KEY")
         .addOnSuccessListener(
             this,
             new OnSuccessListener<RecaptchaHandle>() {
               @Override
               public void onSuccess(RecaptchaHandle handle) {
                 // Handle success ...
                 MainActivity.this.handle = handle;
               }
             })
         .addOnFailureListener(
             this,
             new OnFailureListener() {
               @Override
               public void onFailure(@NonNull Exception e) {
                 if (e instanceof ApiException) {
                   ApiException apiException = (ApiException) e;
                   Status apiErrorStatus = apiException.getStatusCode();
                   // Handle api errors ...
                 } else {
                   // Handle other failures ...
                 }
               }
             });
   }

   public void onClick(View v) {
     // Step 2: call execute() when there is an action to protect.
     Recaptcha.getClient(this)
         .execute(this.handle, new RecaptchaAction(new RecaptchaActionType(RecaptchaActionType.LOGIN)))
         .addOnSuccessListener(
             this,
             new OnSuccessListener<RecaptchaResultData>() {
               @Override
               public void onSuccess(RecaptchaResultData response) {
                 String token = response.getTokenResult();
                 // Handle success ...
                 if (!token.isEmpty()) {
                   Log.d(TAG, "reCAPTCHA response token: " + token);
                   // Validate the response token by following the instructions
                   // when creating an assessment.
                 }
               }
             })
         .addOnFailureListener(
             this,
             new OnFailureListener() {
               @Override
               public void onFailure(@NonNull Exception e) {
                 if (e instanceof ApiException) {
                   ApiException apiException = (ApiException) e;
                   Status apiErrorStatus = apiException.getStatusCode();
                   // Handle api errors ...
                 } else {
                   // Handle other failures ...
                 }
               }
             });
   }

  @Override
  protected void onDestroy() {
    // Step 3: call close() when there is no more action to verify.
   Recaptcha.getClient(this)
       .close(handle)
       .addOnSuccessListener(
           this,
           new OnSuccessListener<Boolean>() {
             @Override
             public void onSuccess(Boolean gotClosed) {
               // Handle success ...
             }
           })
       .addOnFailureListener(
           this,
           new OnFailureListener() {
             @Override
             public void onFailure(@NonNull Exception e) {
               if (e instanceof ApiException) {
                 ApiException apiException = (ApiException) e;
                 Status apiErrorStatus = apiException.getStatusCode();
                 // Handle api errors ...
               } else {
                 // Handle other failures ...
               }
             }
           });
  }
}

Handling 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 RecaptchaStatusCodes.

API reference

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

What's next