SMS-Bestätigung in einer Android-App anfordern

Damit Telefonnummern automatisch bestätigt werden, müssen Sie sowohl den Client- als auch den Serverteil des Bestätigungsvorgangs implementieren. In diesem Dokument wird beschrieben, wie der Clientteil in einer Android-App implementiert wird.

Um den Vorgang zur Bestätigung der Telefonnummer in einer Android-App zu starten, senden Sie die Telefonnummer an Ihren Überprüfungsserver und rufen Sie die SMS Retriever API auf, um auf eine SMS mit einem Einmalcode für Ihre App zu warten. Nachdem Sie die Nachricht erhalten haben, senden Sie den Einmalcode an Ihren Server zurück, um den Bestätigungsprozess abzuschließen.

Hinweis

Führen Sie die Schritte in den folgenden Abschnitten aus, um Ihre App vorzubereiten.

Voraussetzungen für die App

Achten Sie darauf, dass die Build-Datei Ihrer App die folgenden Werte verwendet:

  • minSdkVersion 19 oder höher
  • CompileSdkVersion 28 oder höher

Eigene Anwendung konfigurieren

Fügen Sie in der Datei build.gradle auf Projektebene das Maven-Repository von Google und das Maven Central Repository in den Abschnitten buildscript und allprojects hinzu:

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

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

Fügen Sie die Abhängigkeit von Google Play-Diensten für die SMS Retriever API der Gradle-Build-Datei des Moduls hinzu. Diese ist in der Regel app/build.gradle:

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

1. Telefonnummer des Nutzers abrufen

Sie können die Telefonnummer des Nutzers auf eine für Ihre Anwendung geeignete Weise abrufen. Häufig ist es am besten, die Hinweisauswahl zu verwenden, um den Nutzer zur Auswahl einer der auf dem Gerät gespeicherten Telefonnummern aufzufordern. So muss die Telefonnummer nicht manuell eingegeben werden. So verwenden Sie die Hinweisauswahl:

// 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-Abruf starten

Wenn Sie bereit sind, die Telefonnummer des Nutzers zu bestätigen, rufen Sie eine Instanz des SmsRetrieverClient-Objekts ab, rufen Sie startSmsRetriever auf und hängen Sie Erfolgs- und Fehler-Listener an die SMS-Abrufaufgabe an:

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

Beim SMS-Abruf wird bis zu fünf Minuten lang auf eine SMS gewartet, die einen eindeutigen String zur Identifizierung Ihrer App enthält.

3. Telefonnummer an Ihren Server senden

Nachdem Sie die Telefonnummer des Nutzers ermittelt und mit dem Empfang von SMS begonnen haben, senden Sie die Telefonnummer des Nutzers mit einer beliebigen Methode (in der Regel mit einer HTTPS-POST-Anfrage) an Ihren Überprüfungsserver.

Ihr Server generiert eine Bestätigungsnachricht und sendet sie per SMS an die von Ihnen angegebene Telefonnummer. Weitere Informationen finden Sie unter SMS-Bestätigung auf dem Server durchführen.

4. Bestätigungsnachrichten erhalten

Wenn eine Bestätigungsnachricht auf dem Gerät des Nutzers empfangen wird, senden Play-Dienste explizit einen SmsRetriever.SMS_RETRIEVED_ACTION-Intent an Ihre App, der den Text der Nachricht enthält. Verwenden Sie eine BroadcastReceiver, um diese Bestätigungsnachricht zu erhalten.

Rufen Sie im onReceive-Handler des BroadcastReceiver den Text der Bestätigungsnachricht aus den Extras des Intents ab:

/**
 * 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;
      }
    }
  }
}

Registrieren Sie diese BroadcastReceiver mit dem Intent-Filter com.google.android.gms.auth.api.phone.SMS_RETRIEVED (Wert der Konstante SmsRetriever.SMS_RETRIEVED_ACTION) und der Berechtigung com.google.android.gms.auth.api.phone.permission.SEND (Wert der Konstante SmsRetriever.SEND_PERMISSION) in der Datei AndroidManifest.xml Ihrer Anwendung, wie im folgenden Beispiel, oder dynamisch mithilfe von 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. Senden Sie den einmaligen Code aus der Bestätigungsnachricht an Ihren Server.

Nachdem Sie nun den Text der Bestätigungsnachricht erhalten haben, verwenden Sie einen regulären Ausdruck oder eine andere Logik, um den einmaligen Code aus der Nachricht zu erhalten. Das Format des einmaligen Codes hängt davon ab, wie Sie ihn auf Ihrem Server implementiert haben.

Zum Schluss senden Sie den einmaligen Code über eine sichere Verbindung an Ihren Server. Wenn Ihr Server den einmaligen Code erhält, wird die Bestätigung der Telefonnummer aufgezeichnet.

Optional: Telefonnummer mit Smart Lock für Passwörter speichern

Nachdem der Nutzer seine Telefonnummer bestätigt hat, können Sie den Nutzer auffordern, dieses Telefonnummernkonto mit Smart Lock für Passwörter zu speichern. Dadurch ist es automatisch in anderen Apps und auf anderen Geräten verfügbar, ohne dass Sie die Telefonnummer noch einmal eingeben oder auswählen müssen:

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

Nachdem der Nutzer die App neu installiert oder auf einem neuen Gerät installiert hat, kannst du die gespeicherte Telefonnummer abrufen, ohne den Nutzer noch einmal nach der Telefonnummer fragen zu müssen:

// 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)