Recipe Autosend an SMS Based on a Received SMS

Because most SMS messages are not read by the recipient until hours later, this recipe sends an autoresponse SMS when an SMS is received. This is done by creating an Android service in the background that can receive incoming SMS. An alternative method is to register a broadcast receiver in the AndroidManifest XML file.

The application must declare permission to send and receive SMS in the AndroidManifest XML file, as shown in Listing 8.1. It also declares a main activity SMSResponder that creates the autoresponse and a service ResponderService to send the response when an SMS is received.

Listing 8.1 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cookbook.SMSResponder" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon"

android:label="@string/app_name"> <activity android:name=".SMSResponder"

android:label="@string/app_name"> <intent-filter>

<action android:name="android.intent.action. MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>

<service android:enabled="true" android:name=".ResponderService"> </service>

</application>

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

</manifest>

The main layout file shown in Listing 8.2 contains a LinearLayout with three views: a Textview to display the message used for the autoresponse, a button used to commit changes on the reply message inside the application, and EditText where the user can enter a reply message.

Listing 8.2 res/layout/main.xml

<?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:id="@+id/display" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:textSize="18dp" />

<Button android:id="@+id/submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Change my response" />

<EditText android:id="@+id/editText" android:layout_width="fill_parent" android:layout_height="fill_parent" />

</LinearLayout>

The main activity is shown in Listing 8.3. It starts the service that listens and autore-sponds to SMS messages. It also allows the user to change the reply message and save it in a SharedPreference for future use.

Listing 8.3 src/com/cookbook/SMSresponder/SMSResponder.java package com.cookbook.SMSresponder;

import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle;

import android.preference.PreferenceManager;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public class SMSResponder extends Activity { TextView tv1; EditText ed1; Button bt1;

SharedPreferences myprefs; Editor updater; String reply=null;

^Override public void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState); setContentView(R.layout.main);

myprefs = PreferenceManager.getDefaultSharedPreferences(this);

tv1 = (TextView) this.findViewByld(R.id.display); ed1 = (EditText) this.findViewByld(R.id.editText); bt1 = (Button) this.findViewByld(R.id.submit);

reply = myprefs.getString("reply",

"Thank you for your message. I am busy now. " + "I will call you later"); tvl.setText(reply);

updater = myprefs.edit();

ed1.setHint(reply);

bt1.setOnClickListener(new OnClickListener() { public void onClick(View view) {

updater.putString("reply", ed1.getText().toString());

updater.commit();

SMSResponder.this.finish();

// start Service

Intent svc = new Intent(this, ResponderService.class); startService(svc);

catch (Exception e) {

Log.e("onCreate", "service creation problem", e);

The majority of code is contained in the service, as shown in Listing 8.4. It retrieves the SharedPreferences for this application first.Then it registers a broadcast receiver for listening to incoming and outgoing SMS messages. The broadcast receiver for outgoing SMS messages is not used here but shown for completeness.

The incoming SMS broadcast receiver uses a bundle to retrieve the protocol description unit (PDU), which contains the SMS text and any additional SMS meta-data, and parses it into an Object array.The method createFromPdu() converts the Object array into an SmsMessage.Then the method getOriginatingAddress() can be used to get the sender's phone number, and getMessageBody() can be used to get the text message.

In this recipe, after the sender address is retrieved, it calls the respond() method.This method tries to get the data stored inside the SharedPreferences for the autorespond message. If there is no data stored, it uses a default value. Then, it creates two PendingIntents for sent status and delivered status.The method divideMessage() is used to make sure the message is not oversized. After all the data is managed, it is sent using sendMuiltTextMessage().

Listing 8.4 src/com/cookbook/SMSresponder/ResponderServicejava package com.cookbook.SMSresponder;

import java.util.ArrayList;

import android.app.Activity;

import android.app.PendingIntent;

import android.app.Service;

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.IBinder;

import android.preference.PreferenceManager; import android.telephony.SmsManager; import android.telephony.SmsMessage; import android.util.Log; import android.widget.Toast;

public class ResponderService extends Service {

//The Action fired by the Android-System when a SMS was received. private static final String RECEIVED_ACTION =

"android.provider.Telephony.SMS_RECEIVED"; private static final String SENT_ACTION="SENT_SMS"; private static final String DELIVERED_ACTION="DELIVERED_SMS";

String requester; String reply=""; SharedPreferences myprefs;

^Override public void onCreate() { super.onCreate();

myprefs = PreferenceManager.getDefaultSharedPreferences(this);

registerReceiver(sentReceiver, new IntentFilter(SENT_ACTION)); registerReceiver(deliverReceiver, new IntentFilter(DELIVERED_ACTION));

IntentFilter filter = new IntentFilter(RECEIVED_ACTION);

registerReceiver(receiver, filter);

IntentFilter attemptedfilter = new IntentFilter(SENT_ACTION);

registerReceiver(sender,attemptedfilter);

private BroadcastReceiver sender = new BroadcastReceiver(){ ^Override public void onReceive(Context c, Intent i) { if(i.getAction().equals(SENT_ACTION)) {

if(getResultCode() != Activity.RESULT_OK) {

String reciptent = i.getStringExtra("recipient"); requestReceived(reciptent);

BroadcastReceiver sentReceiver = new BroadcastReceiver() { ^Override public void onReceive(Context c, Intent in) { switch(getResultCode()) {

case Activity.RESULT_OK:

//sent SMS message successfully; smsSent(); break; default:

//sent SMS message failed smsFailed();

break;

public void smsSent() {

Toast.makeText(this, "SMS sent", Toast.LENGTH_SHORT);

public void smsFailed() {

Toast.makeText(this, "SMS sent failed", Toast.LENGTH_SHORT);

public void smsDelivered() {

Toast.makeText(this, "SMS delivered", Toast.LENGTH_SHORT);

BroadcastReceiver deliverReceiver = new BroadcastReceiver() { ^Override public void onReceive(Context c, Intent in) { //SMS delivered actions smsDelivered();

public void requestReceived(String f) {

Log.v("ResponderService","In requestReceived"); requester=f;

BroadcastReceiver receiver = new BroadcastReceiver() { ^Override public void onReceive(Context c, Intent in) { Log.v("ResponderService","On Receive"); reply="";

if(in.getAction().equals(RECEIVED_ACTION)) {

Log.v("ResponderService","On SMS RECEIVE");

Bundle bundle = in.getExtras(); if(bundle!=null) {

Object[] pdus = (Object[])bundle.get("pdus"); SmsMessage[] messages = new SmsMessage[pdus.length]; for(int i = 0; i<pdus.length; i++) {

Log.v("ResponderService","FOUND MESSAGE"); messages[i] =

SmsMessage.createFromPdu((byte[])pdus[i]);

for(SmsMessage message: messages) {

requestReceived(message.getOriginatingAddress());

respond();

^Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId);

public void respond() {

Log.v("ResponderService","Responing to " + requester); reply = myprefs.getString("reply",

"Thank you for your message. I am busy now. " + "I will call you later"); SmsManager sms = SmsManager.getDefault(); Intent sentIn = new Intent(SENT_ACTION);

Pendinglntent sentPIn = PendingIntent.getBroadcast(this,

Intent deliverIn = new Intent(DELIVERED_ACTION); PendingIntent deliverPIn = PendingIntent.getBroadcast(this,

0,deliverIn,0);

ArrayList<String> Msgs = sms.divideMessage(reply); ArrayList<PendingIntent> sentIns = new ArrayList<PendingIntent>(); ArrayList<PendingIntent> deliverIns =

new ArrayList<PendingIntent>();

for(int i=0; i< Msgs.size(); i++) { sentIns.add(sentPIn); deliverIns.add(deliverPIn);

sms.sendMultipartTextMessage(requester, null,

Msgs, sentIns, deliverIns);

^Override public void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); unregisterReceiver(sender);

^Override public IBinder onBind(Intent arg0) { return null;

Character Building Thought Power

Character Building Thought Power

Character-Building Thought Power by Ralph Waldo Trine. Ralph draws a distinct line between bad and good habits. In this book, every effort is made by the writer to explain what comprises good habits and why every one needs it early in life. It draws the conclusion that habits nurtured in early life concretize into impulses in future for the good or bad of the subject.

Get My Free Ebook


Responses

Post a comment