SMS-Bestätigung in einer Android-App anfordern

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

Wenn Sie den Prozess zur Bestätigung der Telefonnummer in einer Android-App starten möchten, senden Sie die Telefonnummer an Ihren Bestätigungsserver. Rufen Sie dann die SMS Retriever API auf, um eine SMS mit einem Einmalcode für Ihre App zu erhalten. Nachdem Sie die Nachricht erhalten haben, senden Sie den Bestätigungscode an Ihren Server zurück, um die Bestätigung abzuschließen.

Hinweis

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

Voraussetzungen für Apps

Die Build-Datei Ihrer App muss folgende Werte enthalten:

  • Eine minSdkVersion von 19 oder höher
  • kompilierSdkVersion 28 oder höher

Eigene App konfigurieren

Füge in der Datei „build.gradle“ auf Projektebene das Maven-Repository Google und das Maven-Repository in den Abschnitten buildscript und allprojects ein:

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

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

Füge die Google Play-Dienste-Abhängigkeit für die SMS Retriever API in die Gradle-Build-Datei des Moduls ein. Diese ist häufig app/build.gradle:

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

1. Telefonnummer des Nutzers abrufen

Die Telefonnummer des Nutzers lässt sich in irgendeiner Weise für Ihre App abrufen. Oft ist es am besten, wenn der Nutzer mit der Hinweisauswahl eine wählen möchte, die zwischen den auf dem Gerät gespeicherten Telefonnummern besteht. So muss er nicht manuell eine Telefonnummer eingeben. 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 auf, rufen Sie startSmsRetriever auf und hängen Sie Listener für Erfolg und Fehler 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
    // ...
  }
});

Die SMS-Abrufaufgabe wartet bis zu fünf Minuten auf eine SMS, die einen eindeutigen String enthält, mit dem Ihre App identifiziert wird.

3. Die Telefonnummer an Ihren Server senden

Nachdem du die Telefonnummer des Nutzers erhalten und mit der Überwachung von SMS begonnen hast, sende die Telefonnummer des Nutzers mit einer beliebigen Methode an deinen Überprüfungsserver (in der Regel mit einer HTTPS-POST-Anfrage).

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 eingeht, wird von den Play-Diensten explizit ein SmsRetriever.SMS_RETRIEVED_ACTION-Intent an Ihre App gesendet, der den Nachrichtentext enthält. Verwende BroadcastReceiver, um diese Bestätigungsnachricht zu erhalten.

Rufe im BroadcastReceiver-Handler onReceive den Text der Bestätigungsnachricht von den 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 (dem Wert der Konstante SmsRetriever.SMS_RETRIEVED_ACTION) und der Berechtigung com.google.android.gms.auth.api.phone.permission.SEND (dem Wert der SmsRetriever.SEND_PERMISSION-Konstante) in der Datei AndroidManifest.xml Ihrer App, wie im folgenden Beispiel, oder dynamisch mit 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. Einmaligen Code aus der Bestätigungsnachricht an Ihren Server senden

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

Senden Sie schließlich den einmaligen Code über eine sichere Verbindung an Ihren Server. Wenn dein Server den einmaligen Code erhält, zeichnet er auf, dass die Telefonnummer bestätigt wurde.

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

Nachdem der Nutzer seine Telefonnummer bestätigt hat, kann er optional dazu aufgefordert werden, dieses Konto mit Smart Lock für Passwörter zu speichern, damit es in anderen Apps und auf anderen Geräten automatisch verfügbar gemacht werden kann, ohne dass er es noch einmal eingeben oder auswählen muss:

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