SMS Retriever API — Saviour from SMS Permission and Call Log

Suneet Srivastava
3 min readJan 5, 2019

If your Android app has been available on play store and uses the very nice feature of SMS based user verification or has permission of Call Log, then your app might get affected by Jan 09, 2019.

:P

If your app is an exception then fill the form and you don’t have to read the whole post, return and just hit claps and enjoy your weekend :D
https://docs.google.com/forms/d/e/1FAIpQLSfCnRaa4b1VuHhE4gVekWJc_V0Zt4XiTlsKsTipTlPg5ECA7Q/viewform

Exception cases : https://support.google.com/googleplay/android-developer/answer/9047303

But if you’re not of the above cases, then you might need to rollout the release asap and need to remove the permission.
PS: I am not here to ruin your weekend but to save you for your upcoming weekends or until your Product manager bangs your head.

Implementation :

Remove all the permission listed in Android Manifest like (READ_SMS, RECEIVE_SMS, CALL_LOG etc) and remove all the implementation of Broadcast receiver or any of the technique that you used for implementing Autoread and verify feature.

Next,
The SMS Retriever API requires :

  1. Phone with Google Play Service v10.2+
  2. An SMS Format

Now, google to build.gradle(app level) and add

implementation 'com.google.android.gms:play-services-auth:16.0.1' 
implementation 'com.google.android.gms:play-services-gcm:16.0.0'

If your app doesn’t have google play services added, redirect -> https://developers.google.com/android/guides/setup#add_google_play_services_to_your_project

Now as you have a broadcast receiver of SMS..In the manifest
edit the intent filter

<receiver android:name=".utils.SmsReceivers"
android:exported="true"
>
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>

In the broadcast reciever, add the following code

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 as per the message
if (listener != null) {
listener.messageRecieved(message);
}
break;
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
//Send your message to the respected activity
if (listener != null) {
listener.messageRecieved("Timeout");
}
break;
}
}
}

In your OTP Activity or Fragment where you’re listening to the SMS Received

Add the following code

SmsRetrieverClient client = SmsRetriever.getClient(this);

Task<Void> task = client.startSmsRetriever();

task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Successfully started retriever, expect broadcast intent
// ...
// inject the listener in broadcast reciever
SmsBroadcastReciever.setListener(new SmsListener() {
@Override
public void messageRecieved(String messageText) {
etOtpNo.setText(messageText); //set your edit text
of otp to text
btnSubmitOtp.performClick(); //perform click to submit
//send the data to your sever or as according to the
tech stack
}

}
});

task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to start retriever, inspect Exception for more details
log.e(TAG,""+e.getLocalizedMessage());
}
});
@Override
public void onStop() {
super.onStop();
if (smsBroadcastReceivers != null) {
smsBroadcastReceivers.setSmsListener(null);
}
}

That’s all for the API Implementation.

Next step, go to your sms provider service and edit the msg text

  • Begin with the prefix <#> or[#]
  • Has the OTP code
  • Hash String at the end, to identify your app [follow the class implementation method, if terminal command causes issues]
  • No longer than 140 Bytes

Bingo!!🔥

Edit : Please note that the hashvalue differs for debug and release version.

--

--