Reading sms to verify otp automatically in android

In this article, you will learn how to read sms and verify otp automatically in android. We are using SMS user consent api for reading sms to verify otp automatically in android.

SMS verification is mandatory nowadays if we use mobile number of user for identification in our apps. For otp verification, User need to read sms from messages app and submit otp in our android apps. To prevent this issue, android provides sms user consent api to read sms and verify otp automatically.

SMS user consent api first displays prompt to user to request read incoming message. So our android apps can read sms and verify otp automatically. If user grants this permission through allow button then we are reading sms to verify otp using sms user consent api.

There are some rules for incoming message. Incoming message must contain one time code. Code should be 4–10 digit alphanumeric and 1 digit must be a number. This message should not be received from any of our contacts. SMS user consent api wait for reading sms for five minutes. If message is not received within five minutes then api throws timeout error.

 

Add following dependencies in your app level build.gradle file

implementation ‘com.google.android.gms:play-services-auth:19.0.0’
implementation ‘com.google.android.gms:play-services-auth-api-phone:17.5.0’
 
 

Retrieve phone number of user

First we need to get phone number of user to read incoming message using sms user consent api. Now we display picker to select phone number in our apps. So we can obtain user’s phone number.

private val PHONE_NUMBER_PICKER_REQUEST = 1

// show the phone number picker to request phone number for verification
private fun requestPicker() {
    val phoneNumberRequest = HintRequest.Builder()
        .setPhoneNumberIdentifierSupported(true)
        .build()
    val getCredentialsClient = Credentials.getClient(this)
    val pickerIntent = getCredentialsClient.getHintPickerIntent(phoneNumberRequest)
    startIntentSenderForResult(
        pickerIntent.intentSender,
        PHONE_NUMBER_PICKER_REQUEST,
        null, 0, 0, 0
    )
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
    PHONE_NUMBER_PICKER_REQUEST ->
    // Get phone number from picker
    if (resultCode == Activity.RESULT_OK && data != null) {
        val getCredential = data.getParcelableExtra<Credential>(Credential.EXTRA_KEY)
        startSMSDetectListener()
    }
    }
}

 
 

Start Reading SMS To Verify OTP Listener

Now we need to detect incoming sms messages to verify otp. So we start this listener after getting user phone number. If you are knowing sender’s phone number then you can pass it in this listener otherwise you can pass null.

private fun startSMSDetectListener() {
    SmsRetriever.getClient(this).also {
        it.startSmsUserConsent(null)
        .addOnSuccessListener {
            Log.e(“SMS Verification”, “SMS Detect Started”)
        }
        .addOnFailureListener {
            Log.e(“SMS Verification”, “SMS Detect Failed”)
        }
    }
}
 
 

Handle Reading SMS To Verify OTP

After detecting incoming message, we need to handle this message using broadcast receiver to verify otp automatically. Our incoming message should follow all rules as I mentioned earlier otherwise prompt will not be displayed to user.

private val SMS_VERIFICATION_REQUEST = 2

private val smsVerificationBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
    if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
        val extras = intent.extras
        val retrieveSMSStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

        when (retrieveSMSStatus.statusCode) {
            CommonStatusCodes.SUCCESS -> {
                // Retrieve sms consent intent
                val smsConsentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                try {
                    // Display sms consent dialog
                    startActivityForResult(smsConsentIntent, SMS_VERIFICATION_REQUEST)
                } catch (e: ActivityNotFoundException) {
                    e.printStackTrace()
                }
            }
            CommonStatusCodes.TIMEOUT -> {
                // Handle timeout error
            }
        }
    }
}
}

override fun onStart() {
    super.onStart()
    val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
    registerReceiver(smsVerificationBroadcastReceiver, intentFilter)
}

override fun onStop() {
    super.onStop()
    unregisterReceiver(smsVerificationBroadcastReceiver)
}

 

Now we need to extract verification code after getting from incoming message. So we can display verification code in our UI.

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        SMS_VERIFICATION_REQUEST ->
            // Get the verification code
            if (resultCode == Activity.RESULT_OK && data != null) {
                // Get SMS message content
                val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
                // Extract verification code
                val oneTimeCode = extractVerificationCode(message)
                edt_verification_code.setText(oneTimeCode)
            } else {
                // Sms user consent denied
            }
    }
}
 

Leave a Reply