Otp (Token) Should Be Automatically Read from the Message

Auto Read OTP from SMS

It's not a good idea because of this Reminder SMS/Call Log Policy Changes.

The recomended way is using SMS Retriever API from Google Play Services. See the Automatic SMS Verification with the SMS Retriever API.

Notice though that your server needs to send the messages following a few rules (message starts with "<#>", includes the OTP plus additional information and ends up with a hash identifying your app).

cannot read OTP from message

Here is my working Broadcast receiver class which will read digits from message body & broadcast with OTP code to related class

You need to add these permissions in menifest file

    <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

<uses-permission-sdk-23 android:name="android.permission.READ_SMS" />
<uses-permission-sdk-23 android:name="android.permission.RECEIVE_SMS" />

Here is my receiver class

public class SmsListener extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub

if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
if (bundle != null) {
//---retrieve the SMS message received---
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
if (Build.VERSION.SDK_INT <= 22) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
} else {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i], bundle.getString("format"));
}
msg_from = msgs[i].getOriginatingAddress();
if (msg_from.contains("PINSMS")) {
String msgBody = msgs[i].getMessageBody();
//String pinNo = msgBody.substring(msgBody.indexOf('"') + 1, msgBody.indexOf('"', msgBody.indexOf('"') + 2));
String pinNo = msgBody.replaceAll("[^0-9]", "");
Log.d("SMS", "From -" + msg_from + " : Body- " + msgBody);
//CodeVerification.insertCode(pinNo);

// Broadcast to Auto read Code sms
final String DISPLAY_MESSAGE_ACTION = context.getPackageName() + ".CodeSmsReceived";
Intent intentCodeSms = new Intent(DISPLAY_MESSAGE_ACTION);
intentCodeSms.putExtra("varificationCode", pinNo);
context.sendBroadcast(intentCodeSms);
}
}
} catch (Exception e) {
Log.d("Exception caught", e.getMessage());
}
}
}
}
}

I have registered this receiver in my class programmatic because i know OTP sms will come after my submit button click & i unregister it after OTP read as i dont want to trigger this receiver for every SMS by registering it in menifest.

SmsListener smsListener = new SmsListener();
try {
unregisterReceiver(smsListener);
} catch (Exception e) {
}
registerReceiver(smsListener, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));

EDIT

Put below receiver in your activity to get OTP code

final String DISPLAY_MESSAGE_ACTION = activity.getPackageName() + ".CodeSmsReceived";
try {
activity.unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
}
activity.registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));

On receiving code below method will be called

 /**
* Receiving Call Log Changed broadcast
*/
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.hasExtra("varificationCode")) {
String youtOTPcode = intent.getStringExtra("varificationCode"));
}
}
};

Read sms only for OTP

try this out.

private BroadcastReceiver SmsListener = new BroadcastReceiver() {

@SuppressWarnings("deprecation")
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
"android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras(); // ---get the SMS message
// passed in---
SmsMessage[] msgs = null;
// String msg_from;
if (bundle != null) {
// ---retrieve the SMS message received---
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage
.createFromPdu((byte[]) pdus[i]);
// msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
// do your stuff
}
} catch (Exception e) {
// Log.d("Exception caught",e.getMessage());
}
}
}
}
};

and as per i did

@Override
protected void onPause() {
super.onPause();
YourActivity.this.unregisterReceiver(SmsListener);
};

@Override
protected void onResume() {
super.onResume();
IntentFilter i = new IntentFilter(
"android.provider.Telephony.SMS_RECEIVED");
YourActivity.this.registerReceiver(SmsListener, i);
}

but as others suggested you can register BroadcastReceiver after request for OTP and unregistered after getting OTP.

Happy Coding.



Related Topics



Leave a reply



Submit