This page explains how to integrate reCAPTCHA Enterprise in your Android app.
If you want to provide visual challenges for suspicious traffic, you can use the SafetyNet reCAPTCHA API.
Before you begin
Create a reCAPTCHA Key for the Android app platform.
Alternatively, you can copy the ID of an existing reCAPTCHA key for Android by performing one of the following steps:
To copy the ID of an existing key from the Google Cloud console, do the following:
Go to the reCAPTCHA Enterprise page.
- In the reCAPTCHA keys list, hold the pointer over the key you want to copy, and then click .
- To copy the ID of an existing key using the REST API, use the projects.keys.list method.
- To copy the ID of an existing key using the gcloud CLI, use the gcloud recaptcha keys list command.
Prepare your Android environment
Native Android
Prepare your development environment by downloading and installing the latest version of Android Studio.
Ensure that you have an app with the minimum Android SDK value set to API 19: Android 4.4 (KitKat). You can either set the minimum SDK of your app to API 19 or create a new mobile app.
If you are creating a new mobile app, create a test application by starting a new Android Studio project:
- Select Empty Activity. If you want to use Jetpack Compose on your app choose Empty Compose Activity.
- Set the language to kotlin.
- Set the minimum SDK value to API 19: Android 4.4 (KitKat).
Ensure that Google's Maven repository
google()
is in the list of repositories in the project-levelbuild.gradle
file as shown in the following snippet:allprojects { repositories { google() } }
For more information, see Google's Maven repository.
To add the reCAPTCHA Enterprise API dependency, add the following build rule to the
dependencies
section of your app-levelbuild.gradle
file.implementation 'com.google.android.recaptcha:recaptcha:18.3.0'
For more information about adding dependencies in Android apps, see Add build dependencies.
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>
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 yourgradle.properties
.android.useAndroidX=true android.enableJetifier=true
For more information, see Migrating to AndroidX.
Flutter
For detailed instructions about using reCAPTCHA Enterprise through Flutter, see the Flutter documentation.
ReactNative
For detailed instructions about using reCAPTCHA Enterprise through React Native, see the React Native documentation.
Integrate reCAPTCHA Enterprise with your Android app
Instantiate a client by using the reCAPTCHA key (KEY_ID) 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, "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. }
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 aLOGIN
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, "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
}
});
}
}
Set a timeout for API calls
You can specify a timeout value for getClient
and execute
APIs by using the
timeout
property of each API.
A default timeout of 10 seconds is used for getClient
and of 5 seconds for
execute
APIs.
Kotlin
Set timeout when calling
getClient
.lifecycleScope.launch { Recaptcha.getClient(application, "KEY_ID", timeout = 20000L) .onSuccess { client -> recaptchaClient = client } .onFailure { exception -> // Handle communication errors ... // See "Handle communication errors" section } }
This code snippet sets the timeout of
getClient
to 20 seconds.Set timeout when calling
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 } }
This code snippet sets the timeout of
execute
to 10 seconds.
Java
Set timeout when calling
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 } });
This code snippet sets the timeout of
getClient
to 20 seconds.Set timeout when calling
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 } });
This code snippet sets the timeout of
execute
to 10 seconds.
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
To assess the reCAPTCHA response token, create an assessment.