reCAPTCHA を Android アプリと統合する

このページでは、Android アプリに reCAPTCHA を統合する方法について説明します。

不審なトラフィックに対して視覚的な問題チャレンジを提供する場合は、SafetyNet reCAPTCHA API を使用できます。

始める前に

  1. reCAPTCHA 用に環境を準備します

  2. Android アプリ プラットフォーム用の reCAPTCHA キーを作成します

    あるいは、次のいずれかの方法で、Android 用の既存の reCAPTCHA キーの ID をコピーできます。

    • Google Cloud コンソールから既存のチェックボックスのキーの ID をコピーするには、次の操作を行います。

      1. [reCAPTCHA] ページに移動します。

        [reCAPTCHA] に移動

      2. reCAPTCHA キーのリストで、コピーするキーの上にポインタを置き、[] をクリックします。
    • REST API を使用して既存のキーの ID をコピーするには、projects.keys.list メソッドを使用します。
    • gcloud CLI を使用して既存のキーの ID をコピーするには、gcloud recaptcha keys list コマンドを使用します。

Android 環境を準備する

をご覧ください。

ネイティブ Android

  1. Android Studio の最新バージョンをダウンロードおよびインストールし、開発環境を準備します。

  2. Android SDK の最小値が API 19: Android 4.4(KitKat)に設定されているアプリがあることを確認します。アプリの最小 SDK を API 19 に設定するか、新しいモバイルアプリを作成できます。

  3. 新しいモバイルアプリを作成する場合は、新しい Android Studio プロジェクトを開始してテスト アプリを作成します。

    1. [Empty Activity] を選択します。アプリで Jetpack Compose を使用する場合は、[Empty Compose Activity] を選択します。
    2. 言語を kotlin に設定します。
    3. SDK の最小値を API 19: Android 4.4(KitKat)に設定します。
  4. 次のスニペットに示すように、Google の Maven リポジトリ google() がプロジェクト レベルの build.gradle ファイル内のリポジトリのリストにあることを確認します。

    allprojects {
        repositories {
            google()
        }
    }
    

    詳細については、Google の Maven リポジトリをご覧ください。

  5. reCAPTCHA API の依存関係を追加するには、アプリレベルの build.gradle ファイルの dependencies セクションに次のビルドルールを追加します。

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

    Android アプリで依存関係を追加する方法については、ビルド依存関係を追加するをご覧ください。

  6. アプリのマニフェストで、最初の <manifest> タグと最初の <application> タグの間にインターネットの権限を追加します(例: AndroidManifest.xml)。reCAPTCHA API にはネットワーク オペレーションが含まれているため、この権限が必要です。

    <manifest ...>
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application ...>
        ...
      </application>
    </manifest>
    
  7. 新しいプロジェクトで AndroidX ライブラリを使用する場合は、SDK を Android 9.0 以降にコンパイルし、次のコード スニペットを gradle.properties に追加します。

    android.useAndroidX=true
    android.enableJetifier=true
    

    詳細については、AndroidX への移行をご覧ください。

Flutter

Flutter で reCAPTCHA を使用する方法について詳しくは、Flutter のドキュメントをご覧ください。

ReactNative

React Native で reCAPTCHA を使用する方法について詳しくは、React Native のドキュメントをご覧ください。

reCAPTCHA を Android アプリと統合する

  1. Android アプリ用に作成した reCAPTCHA キー(KEY_ID)を使用して、クライアントをインスタンス化します。

    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.
    }
    
  2. reCAPTCHA を使用して保護されているアプリのアクションごとに、RecaptchaAction を渡して execute メソッドを呼び出します。reCAPTCHA には組み込みのアクションセットが用意されており、必要に応じてカスタム アクションを作成できます。

    次のコード スニペットは、execute を使用して LOGIN アクションを保護する方法を示しています。

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

次のサンプルコード スニペットは、1 つのアクティビティ アプリでの getClient()execute() メソッドの完全な統合を示しています。

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

API 呼び出しのタイムアウトを設定する

getClient API と execute API のタイムアウト値を指定するには、各 API の timeout プロパティを使用します。

デフォルトのタイムアウトは getClient で 10 秒、execute API で 10 秒です。

Kotlin

  • getClient を呼び出すときのタイムアウトを設定します。

        lifecycleScope.launch {
          Recaptcha.getClient(application, "KEY_ID", timeout = 20000L)
            .onSuccess { client ->
              recaptchaClient = client
            }
            .onFailure { exception ->
              // Handle communication errors ...
              // See "Handle communication errors" section
            }
        }
    

    このコード スニペットでは、getClient のタイムアウトを 20 秒に設定しています。

  • 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
            }
        }
    

    このコード スニペットでは、execute のタイムアウトを 10 秒に設定しています。

Java

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

    このコード スニペットでは、getClient のタイムアウトを 20 秒に設定しています。

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

    このコード スニペットでは、execute のタイムアウトを 10 秒に設定しています。

通信エラーを処理する

アプリが reCAPTCHA サービスと通信できない場合は、API でエラーが発生したことが原因の可能性があります。このようなエラーを適切に処理するロジックをアプリに追加する必要があります。

一般的な API エラーの軽減の詳細については、RecaptchaErrorCode をご覧ください。

API リファレンス

Android 用の reCAPTCHA API の詳細なリファレンスについては、com.google.android.recaptcha をご覧ください。

次のステップ

  • reCAPTCHA レスポンストークンを評価するため、評価を作成する。