Industrial Training




Google reCAPTCHA


In this tutorial, we will learn the working process of Google reCaptcha and integrate it in our Android application. Google's reCaptcha protects our application from malicious traffic. It is implemented using SafetyNet API.


Working of Google reCaptcha

The Google reCAPTCHA is validated by calling the network calls between Android application, SafetyNet server and your server:


  • An Android app makes a request with Site Key to SafetyNet server for reCAPTCHA validation.
  • The SafetyNet server generates the response by captcha token to the Android app using Site key.
  • Captcha token is sent to your server for validating using the Secret key.
  • Your android server makes a request to SafetyNet for validating captcha token using the Secret key.
  • SafetyNet verifies the token response and returns the result as a success or a fail.
  • Your Android server notifies the Android app by validating token and returns the result as a success or a fail.

Generating the reCAPTCHA Site key and Secret key:


Before creating the API keys, read the API terms of services https://developers.google.com/terms/ carefully.


  • Sign-up the Android reCAPTCHA site https://g.co/recaptcha/androidsignup .


  • Provide the input details of label, package name and accept the reCAPTCHA terms and Service.
    Label: It is a unique label for your key. You can use the name of your company or organization. Package Name: It is the package name of your android application.

  • The Site key, Secret key, client-side integration code, and server-side code are generated at next page.

Android example of integrating Google reCAPTCHA


Let's create an example of integrating Google reCAPTCHA in our Android application.


build.gradle


Add the following SafetyNet and Volley dependencies in build.gradle file.


dependencies {  
    implementation 'com.google.android.gms:play-services-safetynet:15.0.1'  
    implementation 'com.android.volley:volley:1.0.0'  
}  
dependencies {  
    implementation 'com.google.android.gms:play-services-safetynet:15.0.1'  
    implementation 'com.android.volley:volley:1.0.0'  
}  

AndroidManifest.xml


Add the internet permission in AndroidManifest.xml file.


< uses-permission android:name="android.permission.INTERNET" />  
< uses-permission android:name="android.permission.INTERNET" />

activity_main.xml


Add the following code in activity_main.xml file.


< ?xml version="1.0" encoding="utf-8"?>  
< android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context="example.javatpoint.com.googlerecaptcha.MainActivity">  
  
    < TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_marginBottom="8dp"  
        android:layout_marginEnd="8dp"  
        android:layout_marginStart="8dp"  
        android:layout_marginTop="8dp"  
        android:text="Google Recaptcha"  
        android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"  
        app:layout_constraintBottom_toBottomOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintHorizontal_bias="0.436"  
        app:layout_constraintLeft_toLeftOf="parent"  
        app:layout_constraintRight_toRightOf="parent"  
        app:layout_constraintStart_toStartOf="parent"  
        app:layout_constraintTop_toTopOf="parent"  
        app:layout_constraintVertical_bias="0.017" />  
  
    < Button  
        android:id="@+id/button"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_marginBottom="52dp"  
        android:layout_marginEnd="8dp"  
        android:layout_marginStart="8dp"  
        android:text="Verify captcha"  
        app:layout_constraintBottom_toBottomOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintStart_toStartOf="parent" />  
  
< /android.support.constraint.ConstraintLayout>  
< ?xml version="1.0" encoding="utf-8"?>  
< android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:app="http://schemas.android.com/apk/res-auto"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context="example.javatpoint.com.googlerecaptcha.MainActivity">  
  
    < TextView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_marginBottom="8dp"  
        android:layout_marginEnd="8dp"  
        android:layout_marginStart="8dp"  
        android:layout_marginTop="8dp"  
        android:text="Google Recaptcha"  
        android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"  
        app:layout_constraintBottom_toBottomOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintHorizontal_bias="0.436"  
        app:layout_constraintLeft_toLeftOf="parent"  
        app:layout_constraintRight_toRightOf="parent"  
        app:layout_constraintStart_toStartOf="parent"  
        app:layout_constraintTop_toTopOf="parent"  
        app:layout_constraintVertical_bias="0.017" />  
  
    < Button  
        android:id="@+id/button"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_marginBottom="52dp"  
        android:layout_marginEnd="8dp"  
        android:layout_marginStart="8dp"  
        android:text="Verify captcha"  
        app:layout_constraintBottom_toBottomOf="parent"  
        app:layout_constraintEnd_toEndOf="parent"  
        app:layout_constraintStart_toStartOf="parent" />  
  
< /android.support.constraint.ConstraintLayout>

MainActivity.java


Add the following code in the MainActivity.java class file. In this class, we make the client side integration with SafetyNet server and get the response in JSON String.
Replace the value of SITE_KEY and SECRET_KEY with your actual Site Key and Secret Key. When clicking on the button, it calls the SafetyNet.getClient() method to get the Site Key, if returns success than call handleSiteVerify() for token verify.
The Volley library is used for the following purpose:


  • The RequestQueue of Volley library maintains the server calls in a queue.
  • StringRequest is used to get the response as JSON String from your server.
  • The setRetryPolicy() method retry the server call if it fails within the time limit.

package example.javatpoint.com.googlerecaptcha;  
  
import android.support.annotation.NonNull;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.Toast;  
import com.android.volley.DefaultRetryPolicy;  
import com.android.volley.Request;  
import com.android.volley.RequestQueue;  
import com.android.volley.Response;  
import com.android.volley.VolleyError;  
import com.android.volley.toolbox.StringRequest;  
import com.android.volley.toolbox.Volley;  
import com.google.android.gms.common.api.ApiException;  
import com.google.android.gms.common.api.CommonStatusCodes;  
import com.google.android.gms.safetynet.SafetyNet;  
import com.google.android.gms.safetynet.SafetyNetApi;  
import com.google.android.gms.tasks.OnFailureListener;  
import com.google.android.gms.tasks.OnSuccessListener;  
import org.json.JSONObject;  
import java.util.HashMap;  
import java.util.Map;  
  
public class MainActivity extends AppCompatActivity implements View.OnClickListener{  
  
    String TAG = MainActivity.class.getSimpleName();  
    Button btnverifyCaptcha;  
    String SITE_KEY = "6LeaN24UAxxxxx_YOUR_SITE_KEY";  
    String SECRET_KEY = "6LeaN24UAxxxxx_YOUR_SECRET_KEY";  
    RequestQueue queue;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        btnverifyCaptcha = findViewById(R.id.button);  
        btnverifyCaptcha.setOnClickListener(this);  
  
        queue = Volley.newRequestQueue(getApplicationContext());  
    }  
  
    @Override  
    public void onClick(View view) {  
        SafetyNet.getClient(this).verifyWithRecaptcha(SITE_KEY)  
                .addOnSuccessListener(this, new OnSuccessListener< SafetyNetApi.RecaptchaTokenResponse>() {  
                    @Override  
                    public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {  
                        if (!response.getTokenResult().isEmpty()) {  
                            handleSiteVerify(response.getTokenResult());  
                        }  
                    }  
                })  
                .addOnFailureListener(this, new OnFailureListener() {  
                    @Override  
                    public void onFailure(@NonNull Exception e) {  
                        if (e instanceof ApiException) {  
                            ApiException apiException = (ApiException) e;  
                            Log.d(TAG, "Error message: " +  
                                    CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));  
                        } else {  
                            Log.d(TAG, "Unknown type of error: " + e.getMessage());  
                        }  
                    }  
                });  
  
    }  
    protected  void handleSiteVerify(final String responseToken){  
        //it is google recaptcha siteverify server  
        //you can place your server url  
        String url = "https://www.google.com/recaptcha/api/siteverify";  
        StringRequest request = new StringRequest(Request.Method.POST, url,  
                new Response.Listener< String>() {  
                    @Override  
                    public void onResponse(String response) {  
                        try {  
                            JSONObject jsonObject = new JSONObject(response);  
                            if(jsonObject.getBoolean("success")){  
                                //code logic when captcha returns true Toast.makeText(getApplicationContext(),String.valueOf(jsonObject.getBoolean("success")),Toast.LENGTH_LONG).show();  
                            }  
                            else{  
                                Toast.makeText(getApplicationContext(),String.valueOf(jsonObject.getString("error-codes")),Toast.LENGTH_LONG).show();  
                            }  
                        } catch (Exception ex) {  
                            Log.d(TAG, "JSON exception: " + ex.getMessage());  
  
                        }  
                    }  
                },  
                new Response.ErrorListener() {  
                    @Override  
                    public void onErrorResponse(VolleyError error) {  
                        Log.d(TAG, "Error message: " + error.getMessage());  
                    }  
                }) {  
            @Override  
            protected Map< String, String> getParams() {  
                Map< String, String> params = new HashMap< >();  
                params.put("secret", SECRET_KEY);  
                params.put("response", responseToken);  
                return params;  
            }  
        };  
        request.setRetryPolicy(new DefaultRetryPolicy(  
                50000,  
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,  
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));  
        queue.add(request);  
    }  
}  
package example.javatpoint.com.googlerecaptcha;  
  
import android.support.annotation.NonNull;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.Toast;  
import com.android.volley.DefaultRetryPolicy;  
import com.android.volley.Request;  
import com.android.volley.RequestQueue;  
import com.android.volley.Response;  
import com.android.volley.VolleyError;  
import com.android.volley.toolbox.StringRequest;  
import com.android.volley.toolbox.Volley;  
import com.google.android.gms.common.api.ApiException;  
import com.google.android.gms.common.api.CommonStatusCodes;  
import com.google.android.gms.safetynet.SafetyNet;  
import com.google.android.gms.safetynet.SafetyNetApi;  
import com.google.android.gms.tasks.OnFailureListener;  
import com.google.android.gms.tasks.OnSuccessListener;  
import org.json.JSONObject;  
import java.util.HashMap;  
import java.util.Map;  
  
public class MainActivity extends AppCompatActivity implements View.OnClickListener{  
  
    String TAG = MainActivity.class.getSimpleName();  
    Button btnverifyCaptcha;  
    String SITE_KEY = "6LeaN24UAxxxxx_YOUR_SITE_KEY";  
    String SECRET_KEY = "6LeaN24UAxxxxx_YOUR_SECRET_KEY";  
    RequestQueue queue;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        btnverifyCaptcha = findViewById(R.id.button);  
        btnverifyCaptcha.setOnClickListener(this);  
  
        queue = Volley.newRequestQueue(getApplicationContext());  
    }  
  
    @Override  
    public void onClick(View view) {  
        SafetyNet.getClient(this).verifyWithRecaptcha(SITE_KEY)  
                .addOnSuccessListener(this, new OnSuccessListener< SafetyNetApi.RecaptchaTokenResponse>() {  
                    @Override  
                    public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {  
                        if (!response.getTokenResult().isEmpty()) {  
                            handleSiteVerify(response.getTokenResult());  
                        }  
                    }  
                })  
                .addOnFailureListener(this, new OnFailureListener() {  
                    @Override  
                    public void onFailure(@NonNull Exception e) {  
                        if (e instanceof ApiException) {  
                            ApiException apiException = (ApiException) e;  
                            Log.d(TAG, "Error message: " +  
                                    CommonStatusCodes.getStatusCodeString(apiException.getStatusCode()));  
                        } else {  
                            Log.d(TAG, "Unknown type of error: " + e.getMessage());  
                        }  
                    }  
                });  
  
    }  
    protected  void handleSiteVerify(final String responseToken){  
        //it is google recaptcha siteverify server  
        //you can place your server url  
        String url = "https://www.google.com/recaptcha/api/siteverify";  
        StringRequest request = new StringRequest(Request.Method.POST, url,  
                new Response.Listener< String>() {  
                    @Override  
                    public void onResponse(String response) {  
                        try {  
                            JSONObject jsonObject = new JSONObject(response);  
                            if(jsonObject.getBoolean("success")){  
                                //code logic when captcha returns true Toast.makeText(getApplicationContext(),String.valueOf(jsonObject.getBoolean("success")),Toast.LENGTH_LONG).show();  
                            }  
                            else{  
                                Toast.makeText(getApplicationContext(),String.valueOf(jsonObject.getString("error-codes")),Toast.LENGTH_LONG).show();  
                            }  
                        } catch (Exception ex) {  
                            Log.d(TAG, "JSON exception: " + ex.getMessage());  
  
                        }  
                    }  
                },  
                new Response.ErrorListener() {  
                    @Override  
                    public void onErrorResponse(VolleyError error) {  
                        Log.d(TAG, "Error message: " + error.getMessage());  
                    }  
                }) {  
            @Override  
            protected Map< String, String> getParams() {  
                Map< String, String> params = new HashMap< >();  
                params.put("secret", SECRET_KEY);  
                params.put("response", responseToken);  
                return params;  
            }  
        };  
        request.setRetryPolicy(new DefaultRetryPolicy(  
                50000,  
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,  
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));  
        queue.add(request);  
    }  
}  

Output:


Hi I am Pluto.