Overview
Welcome visitors, Greetings for the day. Hope you are doing well. As we all know Google is making android app uploading more strict day-by-day, in January 2019 the permission to access unnecessary SMS and call logs has been removed for the non-default apps. However it has introduced a few API to get our job done. Let’s have a look at one such API…
Introduction
The SMS User Consent API allows your app to prompt the consent dialog asking to allow or deny the permission to read specific incoming SMS. After granting the permission, the app can access the whole message body to perform the further SMS verification process. The SMS User Consent API is more user interactive than SMS Retriever API.
When To Use?
The SMS User Consent API does not require any custom format or hashcode in its message body. So If you don’t have control over the SMS body you can use the SMS User Consent API.
As it is recommended by Google, if it is possible we should use SMS Retriever API for SMS verification process because it gives fully automated, more secure and best user experience.
How Does It work?
credits: Google
To implement the SMS verification we need to interact with both, app-side and server-side.
The SMS User Consent API Listener will listen next five minutes for the new messages after it’s triggering.
Let’s Buckle Up For A Demo
1. Creating a new project:
Create a new project in your Android Studio from File ⇒ New Project and select Empty Activity from templates.
2. Adding Dependencies:
Open application level build.gradle file and add required dependencies.
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' // Google Consent API dependency implementation 'com.google.android.gms:play-services-auth-api-phone:17.1.0' // optional for Phone Selector to get the number implementation 'com.google.android.gms:play-services-auth:17.0.0' }
There is an optional API to integrate Google’s phone number selector API to get number from the device. We are not going to implement it in current example but if you wish to this will guide you here
3. Initializing Consent API:
We have to initialize SMS User Consent API, we can mention the specific sender number of SMS so that the play service will look new message only from that specific number or you can pass null so that it will consider any number would be allowed.
// starting SMS User Consent API // we can also pass specific sender number instead of null. val task = SmsRetriever.getClient(context).startSmsUserConsent(SenderNumber or null)
4. Starting to Listen For Incoming Message:
For the next five minutes, when the device receives a new message, the play service will trigger the broadcast with the intent of the prompt which asks permission to read that message.
SmsRetriever.SMS_RETRIEVED_ACTION will be used a handle and respond received Broadcast intent.
The broadcast will be triggered only if the below criteria are fulfilled for the message:
- The message body should contain 4-10 characters alphanumeric string with at least one number.
- The message should be sent from the phone number that shouldn’t be in the user’s contacts.
- If you have specified sender number in code than the service will only listen to messages from that number.
private val SMS_CONSENT_REQUEST = 2 // Set to an unused request code private var 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 -> { // retrieving the consent intent val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT) try { //activity must be started to show consent dialog within 5 minutes // otherwise new timeout intent will be received. startActivityForResult(consentIntent, SMS_CONSENT_REQUEST) } catch (e: ActivityNotFoundException) { Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show() } } CommonStatusCodes.TIMEOUT -> { // Time out Toast.makeText(applicationContext, "Timeout", Toast.LENGTH_LONG).show() } } } } }
We need to register the Broadcast in our class to get the broadcast from play service. Here SmsRetriever.SMS_RETRIEVED_ACTION will work as Intent Filter.
We have to register and unregister in the activity with respect to its life cycle.
override fun onResume() { super.onResume() //Registering broadcast receiver to receive broadcast. val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION) registerReceiver(smsVerificationReceiver, intentFilter) } override fun onPause() { super.onPause() unregisterReceiver(smsVerificationReceiver) }
5. Getting Message:
After asking permission to read that specific message through the prompt Intent, we need to handle the result of it, which will be handled in the onActivityResult method.
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { SMS_CONSENT_REQUEST -> if (resultCode == Activity.RESULT_OK && data != null) { // getting message val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE) Toast.makeText(applicationContext, message, Toast.LENGTH_LONG).show() edt_otp.setText(message) // here, message variable will contain a full message. // you to write your logic to fetch the verification code from the message body. // after getting verification code you can send it to the server or do your further process. } else { Toast.makeText(applicationContext, "Consent denied, please type manually", Toast.LENGTH_LONG).show() //permission denied. User has to type code manually. } } }
There will be two possibilities in onActivityResult:
- If the user has granted the permission we can get message body from intent, we need to add our own logic to get verification-code from message body, which will be totally dependent on message format.
- If the permission is denied than we need to give option to user to type the verification-code manually.
Aaanndd it’s done! Wasn’t is as easy as pie?
TL;DR
SMS User Consent API is new API to read SMS without asking SMS_READ permission, we don’t need to customize and use hashcode like SMS Retriever API in message body to read it. It is very simple and easy to implement in our projects.
To Know More About SMS Verification API:
https://developers.google.com/identity/sms-retriever/choose-an-api