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
How to Solve Nullpointerexception Error in Android
How to Handle One-Shot Operations in Jetpack Compose
Why So Complex to Set Style from Code in Android
How to Set Recyclerview App:Layoutmanager="" from Xml
Android - Firebase Quickstart Email/Password Auth Demo Doesn't Work
Android - Copy Existing Project with a New Name in Eclipse
Waiting for Target Device to Come Online
How to Have a Listview/Recyclerview Inside a Parent Recyclerview
Scale Fit Mobile Web Content Using Viewport Meta Tag
How to Disable Crashlytics During Development
How to Get a Fragment to Remove Itself, I.E. Its Equivalent of Finish()
How to Stop an Animation (Cancel() Does Not Work)
Why Isn't My Vector Drawable Scaling as Expected
Cli on Dalvikvm Fails on Jni Lib
How to Read Text File in Android