Reading incoming SMS messages for verification (OTP) - Android
Nowadays, Applications usually use SMS texts for authentication purposes,
like OTP (One-Time-Passwords), where a message is sent by the service
provider and it is automatically read by the application, verifying it.
This flow helps user to save a lot of apps by switching from the
application to the messenger app and then entering the authentication text
to app again.
In this article, We will learn how to read incoming SMS automatically.
We will need 3 classes to perform to achieve our goal. That will be a
Broadcast Receiver
, a listener
, and an
Activity
.
-
SmsReceiver.java
: This is a broadcast receiver that is called when SMS is received. -
SmsListener.java
: This would be our listener interface that will be passed on to our receiver. -
MainActivity.java
: Our calling code where all the action happens.
Implementation
The first thing we should do is declare permissions and
intent-filter
in
AndroidManifest.xml
file.
>uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <receiver android:name=".SmsReceiver"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
This ensures that this broadcast listener sends the broadcast with SMS
data whenever an SMS is received.
Create a simple interface
SmsListener.java
as follows
public interface SmsListener { public void messageReceived(String messageText); }
Now we will move to the
BroadcastReceiver
class to implement
our core logic.
public class SmsReceiver extends BroadcastReceiver { private static SmsListener mListener; @Override public void onReceive(Context context, Intent intent) { Bundle data = intent.getExtras(); Object[] pdus = (Object[]) data.get("pdus"); for(int i=0;i<pdus.length;i++){ SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]); String sender = smsMessage.getDisplayOriginatingAddress(); //You must check here if the sender is your provider and not another one with same text. String messageBody = smsMessage.getMessageBody(); //Pass on the text to our listener. mListener.messageReceived(messageBody); } } public static void bindListener(SmsListener listener) { mListener = listener; } }
Let's see what goes on behind the covers here, the intent contains PDU
(Protocol Data Unit) objects, which is a protocol for the transfer of SMS
messages in telecoms. We obtain an array of these messages that were sent to
our receiver by the system.
Iterating all these, we create a SmsMessage object using
createFromPdu()
a method as shown.
smsMessage.getDisplayOriginatingAddress()
gives us the sender's
number. smsMessage.getMessageBody()
gives us the message text.
Note that we have called mListener.messageReceived()
here as a
callback when the message is received.
We are now ready with our core classes, let's implement this.
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SmsReceiver.bindListener(new SmsListener() { @Override public void messageReceived(String messageText) { Log.d("Text",messageText); Toast.makeText(MainActivity.this,"Message: "+messageText,Toast.LENGTH_LONG).show(); } }); } }
This is our calling code, it just binds the listener to our receiver by
calling SmsReceiver.bindListener() method and a custom implementation
telling what should be done when a message is received, this is the same
method that is called in our BroadcastReceiver.
Thats it! Now run your project/app and test the desired result.
Works fine while the app is running. Throws error when the app is closed. mListener.messageReceived(messageBody); throws Null object reference. Please help me
ReplyDelete