Browse through more Android tutorials. If you'd like to see a tutorial on any particular topic, do leave a comment in the wishlist page. We frequently post new tutorials along with app releases. You may subscribe to our newsletter to get all updates in your inbox.
Now you can get the latest Java source bundled with each app update. Install the app from Google Play and go to Settings > Extras.

«  Create a notepad/to-do list app Create a currency converter app  »

Create a SMS application with power features

DownloadDownload
By

Keywords: ContentResolver SmsManager AsyncTask ProgressDialog BroadcastReceiver ListActivity AlertDialog Shape drawable PreferenceActivity

Contents

4 « Prev Page

9. Reading SMS

In MainActivity class we had overridden onListItemClick() method of ListActivity to launch a new screen for reading a particular SMS message. Now we will implement the ReadActivity class.




	public class ReadActivity extends Activity {
		
		private TextView tv;
		
		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.read);
			
			tv = (TextView) findViewById(R.id.textView1);
			
			String id = getIntent().getStringExtra("id");
			String[] projection = {"_id", "address", "date", "body"};
			String selection = "_id = ?";
			String[] selectionArgs = {id};
			Cursor c = getContentResolver().query(SmsXp.INBOX_URI, projection, 
													selection, selectionArgs, null);
			if (c.moveToFirst()) {
				setTitle(c.getString(c.getColumnIndex("address")));
				tv.setText(c.getString(c.getColumnIndex("body")));
			}
		}    

	}
					
There is not much in the layout either. Here is an outline of the layout shown above.
	<?xml version="1.0" encoding="utf-8"?>
	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:orientation="vertical" >
		
		<RelativeLayout
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:background="@drawable/bar" >        

		</RelativeLayout>

		<ScrollView
			android:id="@+id/scrollView1"
			android:layout_width="fill_parent"
			android:layout_height="0dip"
			android:layout_weight="1" >

			<TextView
				android:id="@+id/textView1"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:text="TextView" />
		</ScrollView>

	</LinearLayout>
					
The RelativeLayout is shown as empty but it just contains a bunch of ImageButtons. We will see how the toolbar was create using shape drawable. Create an xml file inside drawable folder with the following content.
	<?xml version="1.0" encoding="utf-8"?>
	<shape xmlns:android="http://schemas.android.com/apk/res/android" >
		<gradient
			android:startColor="#8d95a0"
			android:endColor="#485260"
			android:angle="270" />
		<stroke
			android:width="1dp"
			android:color="#485260" />	
	</shape>
					

10. Sending SMS

The layout of compose screen is similar to the one just discussed. Let's take a look at the Activity which implements the functionality of sending SMS.
	public class ComposeActivity extends Activity {
		
		private static final String ACTION_SENT = "com.appsrox.smsxp.SENT";
		private static final int DIALOG_SENDTO = 1;
		
		private EditText et1;
		private ImageButton ib3;	

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.compose);
			setTitle("New Message");
			
			et1 = (EditText) findViewById(R.id.editText1);
			ib3 = (ImageButton) findViewById(R.id.imageButton3);
		}

		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.imageButton3:
				try {
					Intent sendIntent = new Intent(Intent.ACTION_VIEW);
					sendIntent.putExtra("sms_body", et1.getText().toString()); 
					sendIntent.setType("vnd.android-dir/mms-sms");
					startActivity(sendIntent);
					
				} catch (ActivityNotFoundException e) {
					showDialog(DIALOG_SENDTO);
				}			
				break;			
			}
		}	
		
		@Override
		protected Dialog onCreateDialog(int id) {
			switch (id) {
			case DIALOG_SENDTO:
				final EditText et = new EditText(this);
				et.setInputType(EditorInfo.TYPE_CLASS_PHONE);
				return new AlertDialog.Builder(this)
				   .setTitle("To")
				   .setView(et)
				   .setCancelable(true)
				   .setPositiveButton("Send", new DialogInterface.OnClickListener() {
					   public void onClick(DialogInterface dialog, int id) {
						   String to = et.getText().toString().trim();
						   sendSMS(to);
					   }
				   })
				   .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					   public void onClick(DialogInterface dialog, int id) {
						   dialog.dismiss();
					   }
				   })
				   .create();			
			}
			return super.onCreateDialog(id);
		}
		
		private void sendSMS(String to) {
			SmsManager manager = SmsManager.getDefault() ;
			manager.sendTextMessage(to, null, et1.getText().toString(), null, null);
		}

	}
					

There are two ways in which an application can perform an activity. Either it can do it itself or it can launch another application which can handle the intent.
We have used both these ways for sending SMS. In the onclick handler, first we check if there is any default application which can send SMS. We set the proper intent type and put the message as an extra to the intent. If no activity is found, we use SmsManager provided by Android to send the SMS.

We can register BroadcastReceivers to get notified of the status of sending and delivery of SMS.

	private BroadcastReceiver sent = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			switch(getResultCode()) {
			case Activity.RESULT_OK:
				Toast.makeText(ComposeActivity.this, "Sent successfully", 
								Toast.LENGTH_SHORT).show();
				break;
			case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
			case SmsManager.RESULT_ERROR_NO_SERVICE:
			case SmsManager.RESULT_ERROR_NULL_PDU:
			case SmsManager.RESULT_ERROR_RADIO_OFF:
				Toast.makeText(ComposeActivity.this, "Error sending SMS", 
								Toast.LENGTH_LONG).show();
				break;
			}
			
			unregisterReceiver(this);
		}
	};
	
	private void sendSMS(String to) {
		registerReceiver(sent, new IntentFilter(ACTION_SENT));
		
		SmsManager manager = SmsManager.getDefault() ;
		PendingIntent sentIntent = PendingIntent.getBroadcast(this, 0, 
																new Intent(ACTION_SENT), 0);
		manager.sendTextMessage(to, null, et1.getText().toString(), sentIntent, null);
	}
					
The above code snippet shows how we can know the status of sending of message. Similarly we can create a receiver for delivery of message.
There are few other things we can implement in the Activity to improve usability of the application. Like attach a TextWatcher to the EditText field to disable the send button for an empty message.
	et1.addTextChangedListener(new TextWatcher() {
		
		@Override
		public void onTextChanged(CharSequence s, int start, int before, int count) {}
		
		@Override
		public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
		
		@Override
		public void afterTextChanged(Editable s) {
			if (TextUtils.isEmpty(et1.getText().toString()))
				ib3.setEnabled(false);
			else
				ib3.setEnabled(true);
		}
	});
					
Add the above piece of code in the onCreate() method. To support this functionality we can create a selector drawable and set it as the src for the ImageButton in the layout file.
	<?xml version="1.0" encoding="utf-8"?>
	<selector xmlns:android="http://schemas.android.com/apk/res/android" >
		<item android:state_enabled="true" android:drawable="@drawable/send" />
		<item android:state_enabled="false" android:drawable="@drawable/send_" />
	</selector>
						

This completes the tutorial. However, we have skipped few details which you can find in our previous tutorials.
Share the love:  

More Stuff » 4

App Gen
App Name:
Project Name:
Package:
Screens:
Splash
Login
Help
Main
List  Grid  Pager
Detail
Settings
Options:
Action Bar
Navigation Drawer
Dummy Data
Generate
Free Apps