Android, Code

How to use Broadcast Receiver in Android – Send and Receive SMS

Sending SMS is one of the basic features every phone has. In this tutorial we’ll create a SMS Sending Application for Android. You app can also Intercept any incoming SMS and perform task based on pre-defined rules, we’ll use Broadcast receiver for the listening  purpose and write a working code.

Project Name: HelloSMS
Android Level: Android 2.3.3
Application Name: HelloSMS
Package Name: com.vineetdhanawat.hellosms
Create Activity: HelloSMS
Min SDK Version: 10
 

Layout

We’ll start with creating a layout for our main screen.

Components

  • 2 Text Strings
  • 2 Editable Text Box
  • Character Counter in Message
  • Send Button
Send-SMS
The Home Screen of the SendSMS App
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 >
<TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Enter the phone number of the recipient"
 />
<EditText
 android:id="@+id/phoneNo"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
/>
<TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Message"
/>
<EditText
 android:id="@+id/textMessage"
 android:layout_width="fill_parent"
 android:layout_height="160px"
 android:gravity="top"
/>
<TextView
 android:id="@+id/counter"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="160/0"
/>
<Button
 android:id="@+id/sendSMS"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Send SMS"
/>
</LinearLayout>

HelloSMS Main Activity

In the Main HelloSMS Activity, we’ll do 2 things.

  • Bind the Send SMS button to a OnClickListener() for sending sms.
  • Bind the Message Text box to addTextChangedListener() for counter.
package com.vineetdhanawat.hellosms;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class HelloSMS extends Activity {
 // Called when the activity is first created.
  Button sendSMS;
  EditText phoneNo;
  EditText textMessage;
  TextView mCounter;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    sendSMS = (Button) findViewById(R.id.sendSMS);
    phoneNo = (EditText) findViewById(R.id.phoneNo);
    textMessage = (EditText) findViewById(R.id.textMessage);
    mCounter = (TextView) findViewById(R.id.counter);

    textMessage.addTextChangedListener(mTextEditorWatcher);

    // On Click Listener on the sendSMS Button.
    sendSMS.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        String mobNo = phoneNo.getText().toString();
        String message = textMessage.getText().toString();
        if (mobNo.length()>0 && message.length()>0)
          sendSMS(mobNo, message);
        else
          Toast.makeText(getBaseContext(),
          "Please enter both phone number and message.",
          Toast.LENGTH_SHORT).show();
      }
    });
  }
}

The sendSMS() is defined as follows: We do not need to instantiate this class directly, Instead we can call getdefault() to obtain the SmsManager Object. sendTextMessage() send the sms with a PendingIntent. In this case it does nothing, but it can be used to monitor the status of sent SMS.

// Method to send SMS.
private void sendSMS(String phoneNumber, String message)
{
  PendingIntent pi = PendingIntent.getActivity(this, 0,
    new Intent(this, SMS.class), 0);
  SmsManager sms = SmsManager.getDefault();
  sms.sendTextMessage(phoneNumber, null, message, pi, null);
}

Let us modify the code to monitor the Sent / Delivered status of the SMS. We’ll need to use BroadcastReceiver object for the purpose.

// Method to send SMS.
private void sendSMS(String mobNo, String message) {
  String smsSent = "SMS_SENT";
  String smsDelivered = "SMS_DELIVERED";
  PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
     new Intent(smsSent), 0);
  PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
     new Intent(smsDelivered), 0);

  // Receiver for Sent SMS.
  registerReceiver(new BroadcastReceiver(){
    @Override
    public void onReceive(Context arg0, Intent arg1) {
      switch (getResultCode())
      {
        case Activity.RESULT_OK:
          Toast.makeText(getBaseContext(), "SMS sent",
            Toast.LENGTH_SHORT).show();
          break;
        case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
          Toast.makeText(getBaseContext(), "Generic failure",
            Toast.LENGTH_SHORT).show();
          break;
        case SmsManager.RESULT_ERROR_NO_SERVICE:
          Toast.makeText(getBaseContext(), "No service",
            Toast.LENGTH_SHORT).show();
          break;
        case SmsManager.RESULT_ERROR_NULL_PDU:
          Toast.makeText(getBaseContext(), "Null PDU",
            Toast.LENGTH_SHORT).show();
          break;
        case SmsManager.RESULT_ERROR_RADIO_OFF:
          Toast.makeText(getBaseContext(), "Radio off",
            Toast.LENGTH_SHORT).show();
          break;
      }
    }
  }, new IntentFilter(smsSent));

  // Receiver for Delivered SMS.
  registerReceiver(new BroadcastReceiver(){
    @Override
    public void onReceive(Context arg0, Intent arg1) {
      switch (getResultCode())
      {
        case Activity.RESULT_OK:
          Toast.makeText(getBaseContext(), "SMS delivered",
            Toast.LENGTH_SHORT).show();
          break;
        case Activity.RESULT_CANCELED:
          Toast.makeText(getBaseContext(), "SMS not delivered",
            Toast.LENGTH_SHORT).show();
          break;
        }
      }
    }, new IntentFilter(smsDelivered));

  SmsManager sms = SmsManager.getDefault();
  sms.sendTextMessage(mobNo, null, message, sentPI, deliveredPI);
}

Let us now implement the addTextChangedListener() as Counter.

SMS-Counter
Counter Display = No of Chars Left / Required SMS Count
private final TextWatcher mTextEditorWatcher = new TextWatcher() {
  public void beforeTextChanged(CharSequence s, int start,
   int count, int after) {
  }
  public void onTextChanged(CharSequence s, int start,
   int before, int count) {
    //This sets a textview to the current length
    String smsNo;
    if(s.length() == 0)
      smsNo = "0";
    else
    smsNo = String.valueOf(s.length()/160 + 1);
    String smsLength = String.valueOf(160-(s.length()%160));
    mCounter.setText(smsLength+"/"+smsNo);
  }
  @Override
  public void afterTextChanged(Editable arg0) {
    // TODO Auto-generated method stub
  }
};

Permissions

In the AndroidManifest.xml file, we need to add the two permissions SEND_SMS and RECEIVE_SMS

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.vineetdhanawat.hellosms"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".HelloSMS"
            android:label="@string/app_name" >
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

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

Broadcast Receiver (Intercepting SMS)

Applications can intercept Incoming SMS as well. To do so, you need to add <receiver> element inside AndroidManifest.xml . Make sure it is included inside element.

<receiver android:name="com.vineetdhanawat.hellosms.SMSReceiver"
  android:enabled="true">
  <intent-filter>
  <action android:name="android.provider.Telephony.SMS_RECEIVED" />
  </intent-filter>
</receiver>

Add a new Class file SMSReceiver.java. Here we’ll be parsing the intercepted sms and displaying as Toast. But this will Toast all the incoming sms. In case you want to Toast particular senders, use getOriginatingAddress();

package com.vineetdhanawat.hellosms;

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) {
	    // Parse the SMS.
		Bundle bundle = intent.getExtras();
		SmsMessage[] msgs = null;
		String str = "";
		if (bundle != null)
		{
			// Retrieve the SMS.
			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]);
				// In case of a particular App / Service.
                //if(msgs[i].getOriginatingAddress().equals("+91XXX"))
                //{
				str += "SMS from " + msgs[i].getOriginatingAddress();
				str += " :";
				str += msgs[i].getMessageBody().toString();
				str += "n";
                //}
            }
			// Display the SMS as Toast.
            Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
        }
	}
}

That’s it. You can also use two emulators, By default they will have device names as emulator-5554 and emulator-5556. You can test it by sending sms from one of them to another giving emulator-5556 or just 5556 as the number.

App Ideas?

Using the Location Sensing (GPS) post which i posted a while before, and Broadcast Receiver above, It opens up a whole lot possibility of Apps.

Apps like JustDial. Where you have a lot of options like Theatres, Restaurant etc. All you need to do is choose an option. The app detects your location and sends your location to a pre-defined no. The server responds with list of available results (Say nearest Restaurants).

Want to learn more about Android Service and Broadcast Receiver? Check out Vogel’s Blog

Do you have any other Interesting App Ideas? Do share with us in the comments!

Tagged , , , , , , , , , , ,