Easy Ways to Implement Automatic SMS Verification in Android

android devoper indonesia mobile application development

There are many ways to do the verification process in an Android application. As mobile developer, we know that one of the best way is using SMS verification. Since we all know most mobile phone users have a phone number for their phone.

But, input the code that we received from SMS is not user friendly. User has to view all the messages in the phone and see the code on it, then back again to the app to input the code. We, as mobile developer on mobile application deveopment, need “something” that can read those messages and get the code then fill in the field automatically.

Actually, there are many ways to automatically fill the OTP field by reading the message in our phone using READ_SMS permission. But, Google has strictly prohibited the usage of that permission for security purposes. You can read the full explanation here.

Since we can’t use the READ_SMS permission anymore, Google has given some other choices to implement automatic SMS verification using SMS Verification API which includes the automatic and one-tap SMS verification. Let’s find out how they work and implement it in our mobile application development!

Automatic SMS Verification

android - android developer - android developer indonesia - mobile application development - app developer indonesia
Automatic SMS Verification Flow

The automatic SMS verification is the best way to do the SMS verification. Because, users don’t have to do any action and just wait until the verification process is complete. Also, it doesn’t require any permission, but you have to make sure that you follow these criterias:

  1. Messages that are sent to the user’s device must be no longer than 140 bytes.
  2. Message must contains a one-time code that user’s will send back to the server.
  3. Message must contain an 11-character hash string.

Now, let’s implement automatic SMS verification in our app!

Prerequisites

This only works in Android devices with play service version 10.2 or latest.

Import Library

Import these libraries into your app’s gradle to start using SMS Retriever API.

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

Obtain Phone Number

There are several ways to obtain a user’s phone number. The best way that Google recommends is using a hint picker. Look at these codes below.

// 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
      }
  }
}

Start SMS Retriever

After you have got the user’s phone number, then you are ready to start the SMS Retriever to listen to SMS that contains a unique string to identify your app for up to 5 minutes.

// 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
    // ...
  }
});

Browser extension lainnya untuk website developer Indonesia adalah Grid Ruler. Ini bisa dipakai sebagai tools untuk mengukur apakah tiap elemen memiliki jarak yang sama atau tidak.


    Subscribe now and stay updated!


    Send User’s Phone Number to Server

    Then, you should send the user’s phone number to the server for triggering the verification process. The server will send an SMS containing the one-time code and a unique string to identify your app.

    Receive Verification Message

    When a client’s phone receives any message containing a unique string, SMS Retriever API will broadcast the message with SmsRetriever.SMS_RETRIEVED_ACTION intent. Then, you should use a broadcast receiver to receive the verification message.

    /**
     * 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;
          }
        }
      }
    }

    Don’t forget to register your Broadcast Receiver to manifest.

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

    Send OTP Code Back to Your Server

    After you got the message that contains one-time code, use some regex or other logic to extract your code from the message. Then, send that code back to the server.


    One-tap SMS Verification

    Up there, we have talked about how to do Automatic SMS Verification. It will help us as Android developer, for sure, on developing our mobile application. But then, there still another way from Google. Let’s try it as well!

    The other way that Google provides for SMS verification is using One-tap Verification method. This method has a similar process with the previous one, but you don’t have to generate any unique code to verify your application. This method will show a bottom sheet to ask user permission to read the content of a single SMS. If the user gives their consent, your app then will have access to the message and you can get the one-time code on it.

    android - android developer - android developer indonesia - mobile application development - app developer indonesia
    One-tap Verification Process

    Now, let’s implement One-tap verification on your mobile application!

    Import Library

    First thing that you need to do is import these libraries into your app’s gradle.

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

    Obtain User’s Phone Number

    Again, before we start the SMS verification process, we need to obtain the user’s phone number. You can use any method to do this, but Google recommends using a hint picker. See the code below to implement hint picker.

    // 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
          }
      }
    }

    Listening for an Incoming Message

    Same with the previous method, we should start listening for an incoming message before sending that phone number to the server. This listener will listen to any message for up to 5 minutes. In this method, you can specify the phone number that will send a message contains the OTP code. But, if you don’t want to set it, you can fill it with null value.

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

    Another thing that you have to know about this method is you have to make sure your message completes these criterias:

    1. The message contains a 4–10 character alphanumeric string with at least one number.
    2. The message was sent by a phone number that’s not in the user’s contacts.
    3. If you specified the sender’s phone number, the message was sent by that number.

    Implement this code in your Activity class to start listening for an incoming message.

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

    Starting an activity with EXTRA_CONSENT_INTENT means that a bottom sheet will appear to the user to give one-time permission to read the SMS.

    android - android developer - android developer indonesia - mobile application development - app developer indonesia
    Permission Appears

    Get the Verification Code

    In onActivityResult(), if you got the RESULT_OK, it means the user gives you permission to read the SMS and you can get the SMS content from intent.

    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.
                }
        }
    }

    Then, you can extract the code from SMS and send it back to the server to complete the verification process.


    That’s it! We have implemented the verification process using SMS Retriever API to help on our mobile application development. Those are easy to try, aren’t they?

    If you have any questions, please let me know in the comments below!


    References


    Anang Kurniawan is one of Android developer in GITS Indonesia.


    SMS verification is a common thing in an Android application. Android developers at GITS Indonesia have developed many mobile applications for Android. One of them is JRku, an application that is used all around Indonesia, to help user on paying insurance with Jasa Raharja. Want to know more about it? Find out here.


    You need a service to develop Android app for your company?

    CONTACT US

    Do you have a new project?

    Come tell us what you need! Fill out this form and our solution team will response to your email by maximum of 1×24 workday.

    Indonesia

    Head Office

    Summarecon Bandung, Jl. Magna Timur No.106, Bandung, 40296

    Whatsapp (chat only)

    0811-1309-991

    North America

    Branch Office

    166 Geary Str STE 1500 #1368, San Francisco, CA 94108, United States