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 reminder/alarm app Create an instant messaging app  »

Create a SMS application with power features

DownloadDownload

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

Contents

3 « Prev Page


The MainActivity class is responsible for rendering the list view and contains logic for handling all UI events on the screen. Here is an outline of the class.







	public class MainActivity extends ListActivity {
		
		private Typeface font;
		private TextView headingText;

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			requestWindowFeature(Window.FEATURE_NO_TITLE);
			setContentView(R.layout.main);       
			
			font = Typeface.createFromAsset(getAssets(), "fonts/OpenSans.ttf");
			headingText = (TextView) findViewById(R.id.heading_tv);
			headingText.setTypeface(font);
		}   

		@Override
		protected void onResume() {
			super.onResume();
			
			Cursor c = getContentResolver().query(SmsXp.inboxUri, null, null, null, null);
			startManagingCursor(c);		
			
			String[] from = {"address", "date", "body"};
			int[] to = {R.id.textView1, R.id.textView2, R.id.textView3};
			SimpleCursorAdapter adapter = new SimpleCursorAdapter(
					this, 
					R.layout.row, 
					c, 
					from, 
					to);
		
			setListAdapter(adapter);
		}
		
		@Override
		protected void onListItemClick(ListView l, View v, int position, long id) {
			Intent intent = new Intent();
			intent.setClass(this, ReadActivity.class);
			intent.putExtra("id", String.valueOf(id));
			startActivity(intent);
		}
		
	}
					
We created a fonts sub-directory under assets directory in the project structure and placed the .ttf file for the font inside it. Now we can use the font by creating a Typeface instance and setting it to the TextView.
The other important thing to notice is how we read SMS using a content resolver. We have already added the required permission in the manifest file for reading SMS. The important ingredient here is the inbox Uri which we defined in the Application class.
	public static final Uri INBOX_URI = Uri.parse("content://sms/inbox");
					
ContentProvider is an Android component which makes it possible for one application to access data of another application through a ContentResolver.

The SMS inbox uri does not belong to the documented list of content providers provided by Android. You might be interested in reading this article.


We have omitted a lot of code from the Activity class since we have discussed about them in previous articles. So we won't be covering stuffs like custom list view rows, adapter view binder, saving instance state, showing dialogs, etc. in this tutorial.
Next we will implement the functionality of exporting SMS to a text file and sharing the file.

8. SMS Export AsyncTask

One of the buttons in the toolbar allows user to export the list of SMS to a text file for archiving purposes. This is a time consuming task depending on the size of the SMS list, and hence a good candidate for using an AsyncTask.
Create an inner class called ExportTask in MainActivity.
	class ExportTask extends AsyncTask<Void, Integer, Uri> {
    	ProgressDialog pDialog;
    	
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		    pDialog = new ProgressDialog(MainActivity.this);
	        pDialog.setMessage("Exporting to file ...");
	        pDialog.setIndeterminate(false);
	        pDialog.setMax(100);
	        pDialog.setProgress(0);
	        pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
	        pDialog.setCancelable(false);
	        pDialog.show();
		}    	

		@Override
		protected Uri doInBackground(Void... params) {
    		if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
    			FileOutputStream fos = null;
        		try {
        			File f = new File(Environment.getExternalStorageDirectory(), TEMP_FILE);
					fos = new FileOutputStream(f);
					cursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
					int count = cursor.getCount(), i = 0;
					
					StringBuilder sb = new StringBuilder();
					if (cursor.moveToFirst()) {
						do {
							sb.append(cursor.getString(cursor.getColumnIndex("address")))
								.append("\n");
							sb.append(cursor.getString(cursor.getColumnIndex("body")))
								.append("\n");
							sb.append("\n");
							publishProgress(++i*100/count);
						} while (!isCancelled() && cursor.moveToNext());
					}
					fos.write(sb.toString().getBytes());
					return Uri.fromFile(f);
					
				} catch (Exception e) {
				} finally {
					if (fos != null) {
						try {
							fos.close();
						} catch (IOException e) {}
					}
				}
    		}
			
			return null;
		}
		
		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
			pDialog.setProgress(values[0]);
		}		

		@Override
		protected void onPostExecute(Uri result) {
			super.onPostExecute(result);
			pDialog.dismiss();
			
			if (result == null) {
				Toast.makeText(MainActivity.this, "Export task failed!", 
								Toast.LENGTH_LONG).show();
				return;
			}
			
			Intent shareIntent = new Intent();
			shareIntent.setAction(Intent.ACTION_SEND);
			shareIntent.setType("text/*");
			shareIntent.putExtra(Intent.EXTRA_STREAM, result);
			startActivity(Intent.createChooser(shareIntent, "Send file to"));
		}		
   	
    }
					
There are quite a few things to note in the above code snippet. First, we are using a ProgressDialog to notify user about the progress of the export operation. We create a ProgressDialog in onPreExecute() and dismiss it in onPostExecute(). We have overridden onProgressUpdate() method of AsyncTask to set the progress.
Second, the actual work of exporting data is done in doInBackground() method where we first check the availability of SD card. We have already requested permission to write to external storage in the manifest file. Also, we publish progress in each loop which updates the progress bar continously.
Third, in onPostExecute() method we start a new activity for sharing the exported file. We create a chooser so the user will have a choice if multiple methods of sharing is possible.
To execute AsyncTask we need to invoke it in the onclick handler. We have already specified onClick function in main.xml for the export button.
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.imageButton1:
			Intent settingsIntent = new Intent();
			settingsIntent.setClass(this, SettingsActivity.class);
			startActivity(settingsIntent);
			break;
			
		case R.id.imageButton2:
			Intent composeIntent = new Intent();
			composeIntent.setClass(this, ComposeActivity.class);
			startActivity(composeIntent);
			break;
			
		case R.id.imageButton5:
	    	task = new ExportTask();
	    	task.execute();
			break;			
		}
	}
					
And finally we override onPause() method of Mainactivity to cancel the export task if it's still in progress..
	@Override
	protected void onPause() {
		if (task != null) {
			task.cancel(false);
    		task.pDialog.dismiss();
		}
		super.onPause();
	}
					

Next we will implement the activities for reading and composing of messages.
Share the love:  

Next Page » 3

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