Automatically Reading SMS To Verify OTP
In the digital age, security and convenience often go hand-in-hand, particularly in the realm of online transactions. One of the most significant advancements in this area is the use of One-Time Passwords (OTPs) for verification.
A critical aspect of this process is the ability to automatically read SMS to verify OTPs. This functionality not only streamlines user verification processes but also adds an extra layer of security to mobile applications.
Instead of using third party libraries to auto fetch OTP from SMS Inbox ,we can easily do this using Broadcast Receiver. Broadcast receiver allows you to send or receive application events.
Steps To Automatically Reading SMS To Verify OTP
Step1: Open app > res > drawable
Create a new resource file
Add the following xml code to create a custom background
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#dcdcdc"/>
</shape>
Step 2: Create a vector Image use any image clip art.
Open drawable > new > vector Asset
Step 3: Create Layout File for OTP Verification
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_gravity="center"
android:background="@drawable/textsms">
</ImageView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:background="@drawable/edittext_background">
<EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:gravity="center"
android:hint="OTP HERE"
android:inputType="number" />
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:background="#3F51B5"
android:gravity="center"
android:text="Verify"
android:textColor="#FFF" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4: Create a new java class
java < com.example.smsotp < new< java class
Create single Broadcast Receiver i.e SmsReceive to listen to our incoming SMS
eg: sms received is Your OTP is : 4587, Then in above code we have split the complete message string in to 2 parts using “:” this special symbol.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import android.widget.EditText;
import androidx.annotation.RequiresApi;
public class OTP_Receiver extends BroadcastReceiver {
private static EditText editText;
public void setEditText(EditText editText)
{
OTP_Receiver.editText=editText;
}
// OnReceive will keep trace when sms is been received in mobile
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onReceive(Context context, Intent intent) {
//message will be holding complete sms that is received
SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
for(SmsMessage sms : messages)
{
String msg = sms.getMessageBody();
// here we are splitting the sms using " : " symbol
String otp = msg.split(": ")[1];
editText.setText(otp);
}
}
}
Step 5: MainActivity.java
we send request to user to access sms and access the otp if permission is granted
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.EditText;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
EditText otpnumber;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//we ask user permission to auto read sms
requestsmspermission();
otpnumber = (EditText) findViewById(R.id.edittext);
new OTP_Receiver().setEditText(otpnumber);
}
private void requestsmspermission() {
String smspermission = Manifest.permission.RECEIVE_SMS;
int grant = ContextCompat.checkSelfPermission(this, smspermission);
// to check if read SMS permission is granted or not
if (grant != PackageManager.PERMISSION_GRANTED) {
String[] permission_list = new String[1];
permission_list[0] = smspermission;
ActivityCompat.requestPermissions(this, permission_list, 1);
}
}
}
Steps 6: Add Listener i.e broadcast receiver in android manifest file under<application>tag and also add user-permission inside <manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.otpreader">
//add this code to ask permissions to access sms
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.OTPReader">
//add the following receiver code
<receiver android:name=".OTP_Receiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Alternative Way: Using SMS Retriever API
Google’s SMS Retriever API is an efficient way to read SMS messages for OTP without requiring additional permissions. To use this API, follow these steps:
- Generate an App Hash: This unique hash is used to identify your app and should be included in your OTP message.
- Receive the OTP Message: Configure your app to listen for an incoming SMS that contains the OTP and your app hash.
- Extract the OTP: Once the SMS is received, extract the OTP from the message automatically.
Best Practices and Security Considerations
- Privacy Compliance: Always adhere to privacy laws and regulations when accessing and handling SMS messages.
- Timeout for OTP: Implement a timeout for the OTP validity to prevent unauthorized use.
- Rate Limiting: To avoid abuse, limit the number of OTP requests a user can make within a certain time frame.
Conclusion
Automatically reading SMS to verify OTP in Android Studio is a game-changer in terms of security and user experience. By following the steps outlined above, developers can effectively implement this feature, ensuring both convenience and enhanced security for their app users.
Remember to keep user privacy and security at the forefront of your implementation strategy. With these tools and techniques, your Android app will not only be more secure but also provide a smoother and more user-friendly experience.