AndroidアプリでSMS検証をリクエストする

電話番号を自動的に検証するには、検証フローのクライアント部分とサーバー部分の両方を実装する必要があります。このドキュメントでは、Androidアプリにクライアント部分を実装する方法について説明します。

Androidアプリで電話番号の確認フローを開始するには、電話番号を確認サーバーに送信し、SMSレトリーバーAPIを呼び出して、アプリのワンタイムコードを含むSMSメッセージのリッスンを開始します。メッセージを受信したら、ワンタイムコードをサーバーに送り返して、検証プロセスを完了します。

あなたが始める前に

アプリを準備するには、次のセクションの手順を完了します。

アプリの前提条件

アプリのビルドファイルが次の値を使用していることを確認してください。

  • minSdkVersionが19以上
  • 28以上のcompileSdkVersion

アプリを構成する

プロジェクト・レベルのbuild.gradleファイルに含まれるGoogleのMavenのリポジトリMavenの中央リポジトリをあなたの両方にbuildscriptallprojectsセクション:

buildscript {
    repositories {
        google()
        mavenCentral()
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

追加Google PlayのサービスのごへSMSレトリーバーのAPIの依存関係をモジュールのGradleのビルドファイル一般的で、 app/build.gradle

dependencies {
  implementation 'com.google.android.gms:play-services-auth:20.0.1'
  implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'
}

1.ユーザーの電話番号を取得します

アプリに適した方法でユーザーの電話番号を取得できます。多くの場合、ヒントピッカーを使用して、デバイスに保存されている電話番号から選択するようにユーザーに促し、手動で電話番号を入力する必要をなくすことが、ユーザーエクスペリエンスとして最適です。ヒントピッカーを使用するには:

// Construct a request for phone numbers and show the picker
private void requestHint() {
    HintRequest hintRequest = new HintRequest.Builder()
           .setPhoneNumberIdentifierSupported(true)
           .build();

    PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(
            apiClient, hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
            RESOLVE_HINT, null, 0, 0, 0);
}

// Obtain the phone number from the result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == RESOLVE_HINT) {
      if (resultCode == RESULT_OK) {
          Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
          // credential.getId();  <-- will need to process phone number string
      }
  }
}

2.SMSレトリバーを起動します

あなたは、ユーザーの電話番号を確認する準備ができたら、のインスタンスを取得SmsRetrieverClient 、オブジェクトを呼び出すstartSmsRetriever 、そしてSMS検索タスクに成功と失敗のリスナーを添付:

// Get an instance of SmsRetrieverClient, used to start listening for a matching
// SMS message.
SmsRetrieverClient client = SmsRetriever.getClient(this /* context */);

// Starts SmsRetriever, which waits for ONE matching SMS message until timeout
// (5 minutes). The matching SMS message will be sent via a Broadcast Intent with
// action SmsRetriever#SMS_RETRIEVED_ACTION.
Task<Void> task = client.startSmsRetriever();

// Listen for success/failure of the start Task. If in a background thread, this
// can be made blocking using Tasks.await(task, [timeout]);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
  @Override
  public void onSuccess(Void aVoid) {
    // Successfully started retriever, expect broadcast intent
    // ...
  }
});

task.addOnFailureListener(new OnFailureListener() {
  @Override
  public void onFailure(@NonNull Exception e) {
    // Failed to start retriever, inspect Exception for more details
    // ...
  }
});

SMS取得タスクは、アプリを識別する一意の文字列を含むSMSメッセージを最大5分間リッスンします。

3.電話番号をサーバーに送信します

ユーザーの電話番号を取得してSMSメッセージのリッスンを開始したら、任意の方法(通常はHTTPS POST要求を使用)を使用してユーザーの電話番号を検証サーバーに送信します。

サーバーは確認メッセージを生成し、指定した電話番号にSMSで送信します。参照してください。サーバー上のSMS検証を行います

4.確認メッセージを受信します

確認メッセージがユーザーのデバイス上で受信されると、プレイサービスは、明示的にアプリにブロードキャストSmsRetriever.SMS_RETRIEVED_ACTIONメッセージのテキストが含まれているテント、。使用BroadcastReceiver 、この確認メッセージを受信します。

BroadcastReceiveronReceiveハンドラ、テントのエクストラからの確認メッセージのテキストを取得:

/**
 * BroadcastReceiver to wait for SMS messages. This can be registered either
 * in the AndroidManifest or at runtime.  Should filter Intents on
 * SmsRetriever.SMS_RETRIEVED_ACTION.
 */
public class MySMSBroadcastReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
      Bundle extras = intent.getExtras();
      Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

      switch(status.getStatusCode()) {
        case CommonStatusCodes.SUCCESS:
          // Get SMS message contents
          String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
          // Extract one-time code from the message and complete verification
          // by sending the code back to your server.
          break;
        case CommonStatusCodes.TIMEOUT:
          // Waiting for SMS timed out (5 minutes)
          // Handle the error ...
          break;
      }
    }
  }
}

このレジスタBroadcastReceiverインテントフィルタとcom.google.android.gms.auth.api.phone.SMS_RETRIEVED (の値SmsRetriever.SMS_RETRIEVED_ACTION定数)と許可com.google.android.gms.auth.api.phone.permission.SEND (の値SmsRetriever.SEND_PERMISSIONあなたのアプリの中に定数) AndroidManifest.xml使用して、次の例のように、ファイル、または動的にContext.registerReceiver

<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"
          android:permission="com.google.android.gms.auth.api.phone.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
    </intent-filter>
</receiver>

5.確認メッセージからサーバーにワンタイムコードを送信します

検証メッセージのテキストができたので、正規表現またはその他のロジックを使用して、メッセージからワンタイムコードを取得します。ワンタイムコードの形式は、サーバーにどのように実装したかによって異なります。

最後に、安全な接続を介してワンタイムコードをサーバーに送信します。サーバーがワンタイムコードを受信すると、電話番号が確認されたことを記録します。

オプション:Smart Lock forPasswordsを使用して電話番号を保存します

オプションで、ユーザーが電話番号を確認した後、この電話番号アカウントをSmart Lock for Passwordsで保存するようにユーザーに求めることができます。これにより、電話番号を再度入力または選択しなくても、他のアプリや他のデバイスで自動的に使用できるようになります。 :

Credential credential = new Credential.Builder(phoneNumberString)
        .setAccountType("https://signin.example.com")  // a URL specific to the app
        .setName(displayName)  // optional: a display name if available
        .build();
Auth.CredentialsApi.save(apiClient, credential).setResultCallback(
            new ResultCallback() {
                public void onResult(Result result) {
                    Status status = result.getStatus();
                    if (status.isSuccess()) {
                        Log.d(TAG, "SAVE: OK");  // already saved
                    } else if (status.hasResolution()) {
                        // Prompt the user to save
                        status.startResolutionForResult(this, RC_SAVE);
                    }
                }
            });

次に、ユーザーがアプリを再インストールするか、新しいデバイスにアプリをインストールした後、ユーザーに電話番号を再度尋ねることなく、保存された電話番号を取得できます。

// On the next install, retrieve the phone number
mCredentialRequest = new CredentialRequest.Builder()
    .setAccountTypes("https://signin.example.com")  // the URL specific to the developer
    .build();
Auth.CredentialsApi.request(apiClient, mCredentialRequest).setResultCallback(
    new ResultCallback<CredentialRequestResult>() {
        public void onResult(CredentialRequestResult credentialRequestResult) {
            if (credentialRequestResult.getStatus().isSuccess()) {
                credentialRequestResult.getCredential().getId();  // this is the phone number
            }
        }
    });

// Then, initiate verification and sign the user in (same as original verification logic)