Auto read OTP android with SMS User Consent API (2024)

In this blog, I will show how to auto read OTP in android with the help of SMS User Consent API. In our previous blog, we have learned Automatic SMS Verification Android using SMS Retriever API. But it has some difficulty for example

  • SMS should start with<#>tag,
  • SMS should end withapplication hash code, etc.

In this article, I’m going to show you the implementation auto-read OTP using SMS User Consent API. It is complements of SMS Retriever API. Using SMS User Consent API we can achieve auto read OTP by allowing an app to prompt the user to grant access to the content of a single SMS message. When the user gives consent, the app can access the entire message to automatically complete SMS verification.

Flow for Auto Read OTP with SMS User Consent API

Image source google developers website.

There are 3 steps of user flow of this SMS User Consent API
  • Start – The first thing you have to start is listening before sending the message or OTP to the server.
  • Prompt – When the user’s device receives the SMS message containing a one-time code, Google Play services display the contents of the message to the user and asks for consent to make that text available to your app.
  • Read Message – If the user consents, the entire SMS message is made available to your app.
Message Criteria

Google play services imposed the followings SMS criteria

  • It contains a one-time password– The should message contains a 4–10 character alphanumeric string with at least one number.
  • Contacts – The message was sent by a phone number that’snotin the user’s contacts.
  • Timing – The API will look for the One Time Code for a maximum time of 5 minutes.
1. Let’s create a new project in Android Studio

Open to an android studio and create a new project. That project we will implement auto read OTP features. So I’m adding few strings in strings.xml file that we will use this project.

<resources> <string name="app_name">SMS verification</string> <string name="send_otp">Send OTP</string> <string name="generate_otp">Generate OTP</string> <string name="received_message">Received Message</string> <string name="verify_otp">Verify OTP</string></resources>
2. Add SMS User Consent API libraries in your app.

We should add below dependencies in app-level build.gradle in your project.

 // add these lines in your app build.gradle implementation 'com.google.android.gms:play-services-auth:17.0.0' implementation 'com.google.android.gms:play-services-auth-api-phone:17.1.0'
3. Listen to the incoming messages

The next step is to listen to incoming messaging. we can start listening for incoming messages using below method. We can add sender phone number, SMS User Consent API will only trigger on messages from this number. I’m adding null here

 private void startSmsUserConsent() { SmsRetrieverClient client = SmsRetriever.getClient(this); //We can add sender phone number or leave it blank // I'm adding null here client.startSmsUserConsent(null).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { Toast.makeText(getApplicationContext(), "On Success", Toast.LENGTH_LONG).show(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Toast.makeText(getApplicationContext(), "On OnFailure", Toast.LENGTH_LONG).show(); } }); }
4. Create a BroadcastReceiver named is SmsBroadcastReceiver

In SmsBroadcastReceiverListener we will catch SMS and set back using SmsBroadcastReceiverListener callback methods.

package com.smsverification;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.os.Bundle;import com.google.android.gms.auth.api.phone.SmsRetriever;import com.google.android.gms.common.api.CommonStatusCodes;import com.google.android.gms.common.api.Status;public class SmsBroadcastReceiver extends BroadcastReceiver{ SmsBroadcastReceiverListener smsBroadcastReceiverListener; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction() == SmsRetriever.SMS_RETRIEVED_ACTION) { Bundle extras = intent.getExtras(); Status smsRetrieverStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS); switch (smsRetrieverStatus.getStatusCode()) { case CommonStatusCodes.SUCCESS: Intent messageIntent = extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT); smsBroadcastReceiverListener.onSuccess(messageIntent); break; case CommonStatusCodes.TIMEOUT: smsBroadcastReceiverListener.onFailure(); break; } } } public interface SmsBroadcastReceiverListener { void onSuccess(Intent intent); void onFailure(); }}
5. Show the permission consent

When the broadcast receiver catch any message that contains OTP, Google paly services display is contents( BottomSheet ) for asking permission. If the user allows then full messing is available to your app. So let’s register broadcast receiver.

private void registerBroadcastReceiver() { smsBroadcastReceiver = new SmsBroadcastReceiver(); smsBroadcastReceiver.smsBroadcastReceiverListener = new SmsBroadcastReceiver.SmsBroadcastReceiverListener() { @Override public void onSuccess(Intent intent) { startActivityForResult(intent, REQ_USER_CONSENT); } @Override public void onFailure() { } }; IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION); registerReceiver(smsBroadcastReceiver, intentFilter); } @Override protected void onStart() { super.onStart(); registerBroadcastReceiver(); } @Override protected void onStop() { super.onStop(); unregisterReceiver(smsBroadcastReceiver); }
6. Receive message in onActivityResult()

If the user consents, the entire SMS message is made available to your app. we will catch messaging in

 @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQ_USER_CONSENT) { if ((resultCode == RESULT_OK) && (data != null)) { //That gives all message to us. // We need to get the code from inside with regex String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); textViewMessage.setText( String.format("%s - %s", getString(R.string.received_message), message)); getOtpFromMessage(message); } } }
7. Extract OTP from messaging.

Suppose our messaging is “Your OTP is 123456. Please do not share OTP with others “. Now you have to extract OTP from methods using below method.

 private void getOtpFromMessage(String message) { // This will match any 6 digit number in the message Pattern pattern = Pattern.compile("(|^)\\d{6}"); Matcher matcher = pattern.matcher(message); if (matcher.find()) { otpText.setText(matcher.group(0)); } }
8. I’m modifying main activity layout for demonstration

For creating a fully functional sample app, I’m adding TextView for showing messaging and edit text for showing OTP.

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/verify_otp" android:textAllCaps="false" android:textSize="18sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textViewMessage" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="24dp" android:layout_marginEnd="16dp" android:gravity="center" android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" tools:text="@string/received_message" /> <ImageView android:id="@+id/imageView" android:layout_width="150dp" android:layout_height="150dp" android:layout_marginTop="32dp" app:layout_constraintBottom_toTopOf="@+id/editTextOTP" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_otp" /> <EditText android:id="@+id/editTextOTP" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:ems="10" android:gravity="center" android:hint="OTP" android:inputType="number" app:layout_constraintBottom_toTopOf="@+id/button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
9. We almost done, put all java code together in activity files.
package com.smsverification;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import com.google.android.gms.auth.api.phone.SmsRetriever;import com.google.android.gms.auth.api.phone.SmsRetrieverClient;import com.google.android.gms.tasks.OnFailureListener;import com.google.android.gms.tasks.OnSuccessListener;import java.util.regex.Matcher;import java.util.regex.Pattern;public class MainActivity extends AppCompatActivity { private static final int REQ_USER_CONSENT = 200; SmsBroadcastReceiver smsBroadcastReceiver; Button verifyOTP; TextView textViewMessage; EditText otpText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // find view by ids verifyOTP = findViewById(R.id.button); textViewMessage = findViewById(R.id.textViewMessage); otpText = findViewById(R.id.editTextOTP); startSmsUserConsent(); } private void startSmsUserConsent() { SmsRetrieverClient client = SmsRetriever.getClient(this); //We can add sender phone number or leave it blank // I'm adding null here client.startSmsUserConsent(null).addOnSuccessListener(new OnSuccessListener<Void>() { @Override public void onSuccess(Void aVoid) { Toast.makeText(getApplicationContext(), "On Success", Toast.LENGTH_LONG).show(); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Toast.makeText(getApplicationContext(), "On OnFailure", Toast.LENGTH_LONG).show(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQ_USER_CONSENT) { if ((resultCode == RESULT_OK) && (data != null)) { //That gives all message to us. // We need to get the code from inside with regex String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); textViewMessage.setText( String.format("%s - %s", getString(R.string.received_message), message)); getOtpFromMessage(message); } } } private void getOtpFromMessage(String message) { // This will match any 6 digit number in the message Pattern pattern = Pattern.compile("(|^)\\d{6}"); Matcher matcher = pattern.matcher(message); if (matcher.find()) { otpText.setText(matcher.group(0)); } } private void registerBroadcastReceiver() { smsBroadcastReceiver = new SmsBroadcastReceiver(); smsBroadcastReceiver.smsBroadcastReceiverListener = new SmsBroadcastReceiver.SmsBroadcastReceiverListener() { @Override public void onSuccess(Intent intent) { startActivityForResult(intent, REQ_USER_CONSENT); } @Override public void onFailure() { } }; IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION); registerReceiver(smsBroadcastReceiver, intentFilter); } @Override protected void onStart() { super.onStart(); registerBroadcastReceiver(); } @Override protected void onStop() { super.onStop(); unregisterReceiver(smsBroadcastReceiver); }}

Congrats, Let’s use the SMS content API is your application

Conclusion

In this post, we learned how to auto-read OTP android using SMS content API in our application. So let’s recap the step of implementation, basically, three major steps Start Listening messaging, show prompt and Read messaging.

I hope it’s helpful for you, Help me by sharing this post with all your friends who learning android app development.

Get Solution Code

Keep Learning 🙂

  • Firebase in-app messaging android
  • Automatic SMS Verification Android
  • Login with Phone Number Android
  • Auto Scroll ViewPager Android
Auto read OTP android with SMS User Consent API (2024)
Top Articles
Latest Posts
Article information

Author: Francesca Jacobs Ret

Last Updated:

Views: 5747

Rating: 4.8 / 5 (68 voted)

Reviews: 91% of readers found this page helpful

Author information

Name: Francesca Jacobs Ret

Birthday: 1996-12-09

Address: Apt. 141 1406 Mitch Summit, New Teganshire, UT 82655-0699

Phone: +2296092334654

Job: Technology Architect

Hobby: Snowboarding, Scouting, Foreign language learning, Dowsing, Baton twirling, Sculpting, Cabaret

Introduction: My name is Francesca Jacobs Ret, I am a innocent, super, beautiful, charming, lucky, gentle, clever person who loves writing and wants to share my knowledge and understanding with you.