Saturday, November 22, 2014

Android: send SMS programmatically

This tutorial is a continuation of previous post:
http://ukitech.blogspot.com/2014/11/android-calling-activity-from.html

We will learn how to SENT a SMS programmatically.


Step: Improve UI





<LinearLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:orientation="vertical"
              tools:context=".MainActivity">
    <TextView
            android:text="If SMS starts with.. "
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    <EditText
            android:id="@+id/sms_search_text"
            android:layout_marginLeft="32dp"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="CIT299?"/>

    <TextView
            android:text="Respond with the SMS message.."
            android:layout_marginTop="16dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    <EditText
            android:id="@+id/sms_respond_text"
            android:layout_marginLeft="32dp"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="finish this app, study hard, prepare the final"/>

    <TextView
            android:text="Received SMS.."
            android:layout_marginTop="16dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="100dp">
        <TextView
                android:id="@+id/sms_received"
                android:layout_marginLeft="32dp"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:hint="1\n2\n3\n4\n5\n6\n7\n8\n9\n"/>
    </ScrollView>
</LinearLayout>










Step: new class SmsSender.java


package com.chicagoandroid.android.app.sms;
import android.app.PendingIntent;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
 * Created by uki on 11/22/14.
 */
public class SmsSender {
   private static final String TAG = SmsSender.class.getSimpleName();
   Context appContext;
   public SmsSender(Context context) {
      appContext = context;
   }
   public void send(String destinationAddress, String text) {
      if (!PhoneNumberUtils.isWellFormedSmsAddress(destinationAddress)) {
         Log.e(TAG, "SMS number is malformed");
         return;
      }
      SmsManager smsManager = SmsManager.getDefault();
      String scAddress = null; //getMyPhoneNumber();
      PendingIntent sentIntent = null;
      PendingIntent deliveryIntent = null; // broadcast when delivered
      try {
         smsManager.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent);
         Log.w(TAG, "message sent: " + text + " to " + destinationAddress);
      }
      catch (Exception e) {
         Log.e(TAG, "SMS not sent: " + e.getMessage());
         //TODO handle
      }
   }




Step: Send message from SmsParser

   public void processReceivedSms(String smsOriginatingAddress, String smsDisplayMessage) {
      final String tag = TAG + ".processReceivedSms";
      Log.i(tag, "SMS from  " + smsOriginatingAddress);
      Log.i(tag, "SMS body  " + smsDisplayMessage);
      mainActivity.appendSmsToUI("SMS from  " + smsOriginatingAddress + "\n" + smsDisplayMessage);
      String keyword = mainActivity.getSmsTextSearch();
      if (doesSmsStartWith(smsDisplayMessage, keyword)) {
         Log.i(tag, "SMS does start with " + keyword);
         String responseText = mainActivity.getSmsRespondSearch();
         Log.i(tag, "Attempting to respond: " + responseText);
         SmsSender sender = new SmsSender(appContext);
         sender.send(smsOriginatingAddress, responseText);

      }
      else
         Log.e(TAG + ".onReceive", "SMS does not start with " + keyword);
   }



Step: MainActivity - full listing

package com.chicagoandroid.android.app.sms;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
   private EditText etSmsTextSearch, etSmsRespondSearch;
   private TextView smsReceived;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      etSmsTextSearch = (EditText) findViewById(R.id.sms_search_text);
      etSmsRespondSearch = (EditText) findViewById(R.id.sms_respond_text);
      smsReceived = (TextView) findViewById(R.id.sms_received);
      // keep reference to Activity context
      MyApplication myApplication = (MyApplication) this.getApplicationContext();
      myApplication.mainActivity = this;
   }
   public String getSmsTextSearch() {
      String text = etSmsTextSearch.getText().toString();
      //todo save to preferences
      if (text == null || text.equalsIgnoreCase("")) text = "Not Provided";
      return text;
   }
   public String getSmsRespondSearch() {
      String text = etSmsRespondSearch.getText().toString();
      //todo save to preferences
      if (text == null || text.equalsIgnoreCase("")) text = "Not Provided";
      return text;
   }
   public void appendSmsToUI(String text) {
      smsReceived.append(text + "\n");
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      int id = item.getItemId();
      if (id == R.id.action_settings) {
         return true;
      }
      return super.onOptionsItemSelected(item);
   }
}