Monday, June 12, 2017

Example using SafetyNet reCAPTCHA API in Android App

reCAPTCHA Android API announced as part of Google Play Services. It's a simple example to use SafetyNet reCAPTCHA API in Android App. Basically, it follow the steps in the tutorial SafetyNet reCAPTCHA API.



- Create a Android Project in Android Studio as as usually, with minSdkVersion of 14 or higher. We need the Package Names in the next step.

- Visit reCAPTCHA Android signup site, fill in the blanks to get your Site key and Secret key. (Get your own, I will delete my keys after the samples finished.) Copy the keys to your program as String.

- Open SDK Manager in Android Studio, make sure you include Google Repository in your SDK Tools.

- Add the follow Google Play services APIs into your Gradle dependencies:
    compile 'com.google.android.gms:play-services-base:11.0.0'
    compile 'com.google.android.gms:play-services-basement:11.0.0'
    compile 'com.google.android.gms:play-services-safetynet:11.0.0'
    compile 'com.google.android.gms:play-services-tasks:11.0.0'

This video show how to:


Modify the code:

MainActivity.java
package com.blogspot.android_er.recaptcha;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.safetynet.SafetyNet;
import com.google.android.gms.safetynet.SafetyNetApi;

public class MainActivity extends AppCompatActivity
        implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener{

    final String SiteKey = "6LdMKyUUAAAAAN0ndw7byI03_qpbpjxKY-mTQnLw";
    final String SecretKey  = "6LdMKyUUAAAAALjcWovpXgcoXiI4i9ykn1U9qs8I";
    private GoogleApiClient mGoogleApiClient;

    Button btnRequest;
    TextView tvResult;

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

        tvResult = (TextView)findViewById(R.id.result);
        btnRequest = (Button)findViewById(R.id.request);
        btnRequest.setOnClickListener(RqsOnClickListener);

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(SafetyNet.API)
                .addConnectionCallbacks(MainActivity.this)
                .addOnConnectionFailedListener(MainActivity.this)
                .build();

        mGoogleApiClient.connect();
    }

    View.OnClickListener RqsOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            tvResult.setText("");

            SafetyNet.SafetyNetApi.verifyWithRecaptcha(mGoogleApiClient, SiteKey)
                    .setResultCallback(new ResultCallback<SafetyNetApi.RecaptchaTokenResult>() {
                        @Override
                        public void onResult(SafetyNetApi.RecaptchaTokenResult result) {
                            Status status = result.getStatus();

                            if ((status != null) && status.isSuccess()) {

                                tvResult.setText("isSuccess()\n");
                                // Indicates communication with reCAPTCHA service was
                                // successful. Use result.getTokenResult() to get the
                                // user response token if the user has completed
                                // the CAPTCHA.

                                if (!result.getTokenResult().isEmpty()) {
                                    tvResult.append("!result.getTokenResult().isEmpty()");
                                    // User response token must be validated using the
                                    // reCAPTCHA site verify API.
                                }else{
                                    tvResult.append("result.getTokenResult().isEmpty()");
                                }
                            } else {

                                Log.e("MY_APP_TAG", "Error occurred " +
                                        "when communicating with the reCAPTCHA service.");

                                tvResult.setText("Error occurred " +
                                        "when communicating with the reCAPTCHA service.");

                                // Use status.getStatusCode() to determine the exact
                                // error code. Use this code in conjunction with the
                                // information in the "Handling communication errors"
                                // section of this document to take appropriate action
                                // in your app.
                            }
                        }
                    });

        }
    };

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Toast.makeText(this, "onConnected()", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Toast.makeText(this,
                "onConnectionSuspended: " + i,
                Toast.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Toast.makeText(this,
                "onConnectionFailed():\n" + connectionResult.getErrorMessage(),
                Toast.LENGTH_LONG).show();
    }
}


layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_margin="20dp"
    tools:context="com.blogspot.android_er.recaptcha.MainActivity" >

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />
    <Button
        android:id="@+id/request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request SafetyNet reCAPTCHA API"/>
    <TextView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

4 comments:

edger said...

Thanks for your post - very helpful.
But I'm not clear what we're supposed to do for this
// User response token must be validated using the
// reCAPTCHA site verify API.
The developer doc I've read doesn't give much detail or implementation examples.

Erik said...

hello edger,

If you have played the game Pokemon Go before, you will know this.


It is used the detect if the user is a real human or a robot.

Unknown said...

halo. i got error, onconnectionfailed null. How to resolve?

Anonymous said...

But the other key i.e secret key is never used?