Einmalige Einwilligung zum Lesen eines SMS-Bestätigungscodes anfordern

Auf dieser Seite wird beschrieben, wie Sie mit der SMS User Consent API die Nutzereinwilligung zum Lesen einer einzelnen SMS-Bestätigungsnachricht anfordern. Wenn der Nutzer einwilligt, gibt die API den Text der Nachricht zurück. Daraus können Sie den Bestätigungscode abrufen und den Bestätigungsprozess abschließen.

Abhängigkeiten installieren

Fügen Sie die Play-Dienste-Authentifizierungskomponente in die build.gradle-Datei Ihrer App ein:

implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0'

1. Telefonnummer des Nutzers abrufen

Wenn Sie die Telefonnummer des Nutzers nicht haben, fordern Sie sie an, bevor Sie einen SMS-Bestätigungsprozess starten.

Sie können die Telefonnummer des Nutzers auf eine für Ihre App geeignete Weise abrufen. Verwenden Sie die Smart Lock für Passwörter-Hinisauswahl , um dem Nutzer zu helfen, seine Telefonnummer einzugeben, wenn diese Informationen nicht erforderlich waren , um das Konto des Nutzers zu erstellen. So verwenden Sie die Hinisauswahl:

Kotlin

private val CREDENTIAL_PICKER_REQUEST = 1  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private fun requestHint() {
    val hintRequest = HintRequest.Builder()
        .setPhoneNumberIdentifierSupported(true)
        .build()
    val credentialsClient = Credentials.getClient(this)
    val intent = credentialsClient.getHintPickerIntent(hintRequest)
    startIntentSenderForResult(
        intent.intentSender,
        CREDENTIAL_PICKER_REQUEST,
        null, 0, 0, 0
    )
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        CREDENTIAL_PICKER_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                val credential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
                // credential.getId();  <-- will need to process phone number string
            }
        // ...
    }
}

Java

private static final int CREDENTIAL_PICKER_REQUEST = 1;  // Set to an unused request code

// Construct a request for phone numbers and show the picker
private void requestHint() throws IntentSender.SendIntentException {
    HintRequest hintRequest = new HintRequest.Builder()
            .setPhoneNumberIdentifierSupported(true)
            .build();
    PendingIntent intent = Credentials.getClient(this).getHintPickerIntent(hintRequest);
    startIntentSenderForResult(intent.getIntentSender(),
            RESOLVE_HINT, null, 0, 0, 0);
}

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

2. Auf eingehende Nachrichten warten

Rufen Sie als Nächstes die Methode startSmsUserConsent() der SMS User Consent API auf, um auf eingehende Nachrichten zu warten. Wenn Sie die Telefonnummer kennen, von der die SMS gesendet wird, geben Sie sie an (andernfalls übergeben Sie null). Auf diese Weise wird die SMS API für die Nutzereinwilligung nur bei Nachrichten von dieser Nummer ausgelöst.

So warten Sie auf Nachrichten:

Kotlin

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
val task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */)

Java

// Start listening for SMS User Consent broadcasts from senderPhoneNumber
// The Task<Void> will be successful if SmsRetriever was able to start
// SMS User Consent, and will error if there was an error starting.
Task<Void> task = SmsRetriever.getClient(context).startSmsUserConsent(senderPhoneNumber /* or null */);

Sobald Sie auf eingehende SMS warten, können Sie Ihr Bestätigungssystem den Bestätigungscode an die Telefonnummer des Nutzers senden lassen, die Sie im ersten Schritt erhalten haben.

Wenn das Gerät in den nächsten fünf Minuten eine SMS mit einem Einmalcode empfängt, senden die Play-Dienste eine Broadcast-Intent an Ihre App, um den Nutzer um die Berechtigung zum Lesen der Nachricht zu bitten. Eine Nachricht löst die Broadcast nur aus, wenn sie die folgenden Kriterien erfüllt:

  • Die Nachricht enthält eine alphanumerische Zeichenfolge mit 4 bis 10 Zeichen und mindestens einer Zahl.
  • Wenn Sie die Telefonnummer des Absenders angegeben haben, wurde die Nachricht von dieser Nummer gesendet.

Verarbeiten Sie diese Broadcasts mit einem Übertragungsempfänger, der die Berechtigung SEND_PERMISSION hat und auf SMS_RETRIEVED_ACTION-Intents reagiert. So erstellen und registrieren Sie den Übertragungsempfänger:

Kotlin

private val SMS_CONSENT_REQUEST = 2  // Set to an unused request code
private val smsVerificationReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

            when (smsRetrieverStatus.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    // Get consent intent
                    val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
                    } catch (e: ActivityNotFoundException) {
                        // Handle the exception ...
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    // Time out occurred, handle the error.
                }
            }
        }
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    // ...

    val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter)
}

Java

private static final int SMS_CONSENT_REQUEST = 2;  // Set to an unused request code
private final BroadcastReceiver smsVerificationReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
            Bundle extras = intent.getExtras();
            Status smsRetrieverStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

            switch (smsRetrieverStatus.getStatusCode()) {
                case CommonStatusCodes.SUCCESS:
                    // Get consent intent
                    Intent consentIntent = extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT);
                    try {
                        // Start activity to show consent dialog to user, activity must be started in
                        // 5 minutes, otherwise you'll receive another TIMEOUT intent
                        startActivityForResult(consentIntent, SMS_CONSENT_REQUEST);
                    } catch (ActivityNotFoundException e) {
                        // Handle the exception ...
                    }
                    break;
                case CommonStatusCodes.TIMEOUT:
                    // Time out occurred, handle the error.
                    break;
            }
        }
    }
};

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

    // ...

    IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
    registerReceiver(smsVerificationReceiver, SmsRetriever.SEND_PERMISSION, intentFilter);
}

Wenn Sie eine Aktivität für EXTRA_CONSENT_INTENT starten, bitten Sie den Nutzer um die einmalige Berechtigung, den Inhalt der Nachricht zu lesen.

3. Bestätigungscode aus einer Nachricht abrufen

Verarbeiten Sie in der Methode onActivityResult() die Antwort des Nutzers auf Ihre Berechtigungsanfrage. Wenn Sie den Ergebniscode RESULT_OK erhalten, hat der Nutzer die Berechtigung zum Lesen des Inhalts der Nachricht erteilt und Sie können den Nachrichtentext aus der Intent abrufen.

Kotlin

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        // ...
        SMS_CONSENT_REQUEST ->
            // Obtain the phone number from the result
            if (resultCode == Activity.RESULT_OK && data != null) {
                // Get SMS message content
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                // Extract one-time code from the message and complete verification
                // `message` contains the entire text of the SMS message, so you will need
                // to parse the string.
                val oneTimeCode = parseOneTimeCode(message) // define this function

                // send one time code to the server
            } else {
                // Consent denied. User can type OTC manually.
            }
    }
}

Java

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        // ...
        case SMS_CONSENT_REQUEST:
            if (resultCode == RESULT_OK) {
                // Get SMS message content
                String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE);
                // Extract one-time code from the message and complete verification
                // `sms` contains the entire text of the SMS message, so you will need
                // to parse the string.
                String oneTimeCode = parseOneTimeCode(message); // define this function

                // send one time code to the server
            } else {
                // Consent canceled, handle the error ...
            }
            break;
    }
}

Sobald Sie den Nachrichtentext haben, können Sie den Bestätigungscode parsen und das Formular automatisch ausfüllen oder den Bestätigungsprozess auf andere Weise abschließen.