Receive SMS using Android BroadcastReceiver inside an activity
Today I am going to share you a very usefull code.
In one of my project I have a situation where I need to verify the user Mobile number with the SMS verification code coming from server to mobile number.
So I need to read SMS for verification mobile number, and there was another point is We just wait only for 30 sec to receive SMS if SMS comes and then check validation code else say Authentication fails. or time expires .
A SMS in Android is
intercepted by using BroadcastReceiver which
then can be used to launch an activity, but in our case we
want the BroadcastReceiver to send theSMS to our Activity when it is in the foreground rather than
launching a new activity everytime.
We start by creating a
BroadcastReceiver – SmsReceiver.java
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import android.os.Bundle;
import
android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context
context, Intent intent) {
Bundle
extras = intent.getExtras();
if (extras == null)
return;
// To display a
Toast whenever there is an SMS.
//
Toast.makeText(context,"Recieved",Toast.LENGTH_LONG).show();
Object[]
pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage
SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String
sender = SMessage.getOriginatingAddress();
String
body = SMessage.getMessageBody().toString();
// A custom Intent
that will used as another Broadcast
Intent
in = new Intent("SmsMessage.intent.MAIN").putExtra(
"get_msg", sender + ":" + body);
// You can place
your check conditions here(on the SMS or the
// sender)
// and then send
another broadcast
context.sendBroadcast(in);
// This is used to
abort the broadcast and can be used to silently
// process incoming
message and prevent it from further being
// broadcasted.
Avoid this, as this is not the way to program an
// app.
//
this.abortBroadcast();
}
}
}
We create our own BroadcastReceiver
that will intercept the SMS and retrieve the body & the sender. Then it
broadcasts another Intent that will is handled by our app in the foreground.
Lets register the BroadcastReceiver(SmsReceiver) in the android-manifest.xmlfile (inside
Lets register the BroadcastReceiver(SmsReceiver) in the android-manifest.xmlfile (inside
<receiver android:name="com.itdeveloper.khurram.SmsReceiver"
>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"
/>
</intent-filter>
</receiver>
You can set the priority
of the receiver to 999 , if you wish to intercept the message and not let it
pass through. (Not a good thing to do)
Now lets add the permission -
<uses-permission android:name="android.permission.RECEIVE_SMS" />
Your manifest xml look like
<?xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itdeveloper.khurram"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.RECEIVE_SMS"
/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itdeveloper.khurram.SignInWaitingActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN"
/>
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<receiver android:name="com.itdeveloper.khurram.SmsReceiver"
>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"
/>
</intent-filter>
</receiver>
</application>
</manifest>
Now lets create our Activity that
will display the SMS when received –
SignInWaitingActivity
package
com.itdeveloper.khurram;
import
android.app.Activity;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import
android.os.CountDownTimer;
import android.preference.PreferenceManager;
import android.util.Log;
import
android.widget.ProgressBar;
import
android.widget.TextView;
import
android.widget.Toast;
public class
SignInWaitingActivity extends Activity {
private BroadcastReceiver mIntentReceiver;
TextView
timerTv;
TextView
mobNoVeryfyTv;
private ProgressBar progressBar;
static Boolean timeOut = true;
@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_in_waiting);
mobNoVeryfyTv = (TextView)
findViewById(R.id.SW_MobNoVeryfyDesctxt);
timerTv = (TextView)
findViewById(R.id.SW_TimeRemainigTv);
progressBar = (ProgressBar)
findViewById(R.id.SW_progressBar);
// show 30 second
time count down
new
CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished)
{
timerTv.setText("Seconds
Remaining : " + millisUntilFinished
/
1000);
}
public void onFinish() {
timerTv.setText("Time
Over");
// SignInWaitingActivity.this.finish();
}
}.start();
}
@Override
protected void onResume() {
super.onResume();
IntentFilter
intentFilter = new IntentFilter("SmsMessage.intent.MAIN");
mIntentReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context
context, Intent intent) {
String
msg = intent.getStringExtra("get_msg");
// Process the sms
format and extract body & phoneNumber
msg
= msg.replace("\n", "");
String
body = msg.substring(msg.lastIndexOf(":") + 1,
msg.length());
String
pNumber = msg.substring(0, msg.lastIndexOf(":"));
// Add it to the
list or do whatever you wish to
Log.e("onResume", "" + msg + body +
pNumber);
Toast.makeText(getApplicationContext(),
body, 1).show();
// check body
content with your validation code mine is
// success123
if
(body.equalsIgnoreCase("success123")) {
Toast.makeText(getApplicationContext(),
"Authentication
Success.", 1).show();
mobNoVeryfyTv.setText("Authentication
Success.");
}
else {
// if message is
contains some invalide code
mobNoVeryfyTv.setText("Authentication
Fails.");
// SignInWaitingActivity.this.finish();
}
}
};
this.registerReceiver(mIntentReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.mIntentReceiver);
}
}
and your xml as
activity_sign_in_waiting.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/imagesbg" >
<TextView
android:id="@+id/SW_MobNoVeryfyDesctxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:text="Waiting for verification sms"
android:textColor="@android:color/white"
android:textSize="14sp" />
<TextView
android:id="@+id/SW_TimeRemainigTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/SW_progressBar"
android:layout_centerHorizontal="true"
android:text="00:00"
android:textColor="@android:color/white" />
<ProgressBar
android:id="@+id/SW_progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/SW_MobNoVeryfyDesctxt"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
We declare a BroadcastReciever in the class itself rather
than the manifest in
theonResume() method
so that when the app returns in the foreground , it should receive the SMS.
Note
– As per Honeycomb 3.0+ it is necessary to launch the activity once, in order
to register the BroadcastReceiver defined in the manifest.
The onRecieve() method of the BroadcastReceiver uses
the same Intent using the corresponding intent filter “SmsMessage.intent.MAIN” defined
inSmsReceiver.
You can use the incoming
message body/number and filter out the required messages for controlling or
updating the UI of the app.
Note that SmsReceiver (BroadcastReceiver) will keep on
intercepting the SMS
in the background but
you can only see these messages when the app is in the foreground. You can save
these messages in the database for further user (or use inbox to retrieve them
later).
I used this technique to
create a Spring MVC & Android (SMS) based quiz , where questions appear
with options A,B,C,D in the browser and you can answer these questions by
messaging it to the app. The app is synced with Spring MVC web app using HTTP POST & GET request.
you can download complete example from here
No comments:
Post a Comment