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!
Table of Contents
ToggleAutomatic SMS Verification
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:
- Messages that are sent to the user’s device must be no longer than 140 bytes.
- Message must contains a one-time code that user’s will send back to the server.
- 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.
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.
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:
- The message contains a 4–10 character alphanumeric string with at least one number.
- The message was sent by a phone number that’s not in the user’s contacts.
- 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.
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
- SMS Verification APIs
- New way of SMS Retriever API — SMS User Consent
- Android automatic SMS verification — Google’s SMS retriever API
- No more SMS, Call Log permissions, Now what?
- Automatic SMS Verification with SMS User Consent — Android Developers
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.