This page describes how to use the SMS User Consent API to request user consent
to read a single SMS verification message. If the user consents, the API returns
the text of the message, from which you can get the verification code and
complete the verification process.

## Install dependencies

Include the Play Services auth component in your app's `build.gradle` file:

    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. Get the user's phone number

If you don't have the user's phone number, request it before you start an SMS
verification flow.

You can obtain the user's phone number in a manner that is appropriate for your
app. Consider using the
[Smart Lock for Passwords hint selector](https://developers.google.com/identity/smartlock-passwords/android/retrieve-hints)
to help the user fill out their phone number if that information wasn't required
to create the user's account. To use the hint selector:

### 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. Start listening for incoming messages

Next, call the SMS User Consent API's `startSmsUserConsent()` method to start
listening for incoming messages. If you know the phone number from which the SMS
message will originate, specify it (otherwise, pass `null`). This way, the SMS
User Consent API will only trigger on messages from this number.

To start listening:

### 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 */);

Once you're listening for incoming SMS messages, you can have your verification
system send the verification code to the user's phone number, which you got in
the first step.

For the next five minutes, when the device receives an SMS message that contains
a one-time code, Play services will broadcast to your app an intent to prompt
the user for permission to read the message. A message triggers the broadcast
only if it meets these criteria:

- The message contains a 4-10 character alphanumeric string with at least one number.
- If you specified the sender's phone number, the message was sent by that number.

Handle these broadcasts with a broadcast receiver that has the `SEND_PERMISSION`
permission and responds to `SMS_RETRIEVED_ACTION` intents. To create and
register the broadcast receiver:

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

By starting an activity for `EXTRA_CONSENT_INTENT`, you prompt the user for
one-time permission to read the contents of the message.

> [!IMPORTANT]
> **Important:** You can detect that the broadcast intent is from SMS Retriever API by adding the `com.google.android.gms.auth.api.phone.permission.SEND` permission to your receiver. This permission setting is available in Google Play services version 19.8.31 or higher.

> [!IMPORTANT]
> **Important:** Do not add the permission `com.google.android.gms.auth.api.phone.permission.SEND` to your app. This permission should only be used to detect the intent is from the SMS Retriever API on the broadcast receiver.

## 3. Get the verification code from a message

In the `onActivityResult()` method, handle the user's response to your request
for permission. If you get a result code of `RESULT_OK`, the user granted
permission to read the contents of the message, and you can get the message text
from the intent.

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

Once you have the message text, you can parse out the verification code and
auto-fill the form or otherwise complete the verification flow.