Archive

Posts Tagged ‘message’

Create an application auto receiving new message (SMS)

July 14, 2011 27 comments

It’s quite a long time that I’ve been writing any new interesting tutorial. Today, I’ve got a little fever so I couldn’t step to workplace; so I decide to spend a little time to write a new tutorial.

The application we’re going to make today is a simple one that will receiving new messages automatically, notify and display them on a ListView. This is gonna be our simple screen:

SMS Auto Receiver

SMS Auto Receiver

A – Create the Project

Project Name: SMS Auto Receiver

Application Name: SMSAutoReceiver

Package Name: pete.android.study

Create Activity: MainActivity

Min SDK: 10

Click OK -> Done with creating project.

B – Sketch the Layout

The layout is pretty much the same as many previous articles on ListView in my blog.

+ One layout for main screen display, which is the list view

+ One layout for each item in the list view, which will be set to list view. This is where our SMS messages residing.

First, we start with layout for each item in list view.

1. List Item Layout

– First row determines the number of sender, I just make it into a LinearLayout with a constant TextView on the left with text “From: “ and right TextView gonna be used for setting incoming number.

– The second row displays the contents of message.

<?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="wrap_content">

	<LinearLayout
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
	>
		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="From: "
		/>

		<TextView
			android:id="@+id/tvNumber"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
		/>

	</LinearLayout>

	<TextView
		android:id="@+id/tvContent"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:singleLine="true"
		android:ellipsize="marquee"
	/>

</LinearLayout>

2. Main Layout

– Just a ListView, no more, no less!!!

C – Class Design – On the Idea

This is what I mapped from my mind.

Clss Diagram

Class Diagram

SmsInfo class: hold information about new message, which is also implement from interface Parcelable in order to be passed through by Intent.

SmsInfoAdapter class: the adapter manages content on ListView, extends from class ArrayAdapter<SmsInfo> for simplisticity.

SmsReceiver class: extends from class BroadcastReceiver, to handle the event when new message arrived, pass these messages to Intent and pass to launch MainActivity.

MainActivity class: is a actual class receiving list of new message (List<SmsInfo>) sending from

D – From Design to Code (w/ Passion)

1. SmsInfo.java

package pete.android.study;

import android.os.Parcel;
import android.os.Parcelable;

public class SmsInfo implements Parcelable {
	private String mNumber;
	private String mContent;

	public SmsInfo(String number, String content) {
		mNumber = number;
		mContent = content;
	}

	public SmsInfo(Parcel in) {
		String data[] = new String[2];
		in.readStringArray(data);
		mNumber = data[0];
		mContent = data[1];
	}

	public void setNumber(String number) {
		mNumber = number;
	}
	public String getNumber() {
		return mNumber;
	}

	public void setContent(String content) {
		mContent = content;
	}
	public String getContent() {
		return mContent;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeStringArray(new String[] {
			mNumber, mContent
		});

	}

	public static final Parcelable.Creator<SmsInfo> CREATOR = new Parcelable.Creator<SmsInfo> () {

		@Override
		public SmsInfo createFromParcel(Parcel source) {

			return new SmsInfo(source);
		}

		@Override
		public SmsInfo[] newArray(int size) {

			return new SmsInfo[size];
		}

	};
}

2. SmsInfoAdapter.java

package pete.android.study;

import java.util.List;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class SmsInfoAdapter extends ArrayAdapter<SmsInfo> {

	public SmsInfoAdapter(Activity a, List<SmsInfo> list) {
		super(a, 0, list);

	}

	@Override
	public View getView(int pos, View convertView, ViewGroup parent) {

		ViewHolder holder = null;
		if(convertView == null) {
			Activity a = (Activity)getContext();
			LayoutInflater inflater = a.getLayoutInflater();
			holder = new ViewHolder();
			convertView = inflater.inflate(R.layout.listitem, null);
			holder.tvNumber = (TextView)convertView.findViewById(R.id.tvNumber);
			holder.tvContent = (TextView)convertView.findViewById(R.id.tvContent);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder)convertView.getTag();
		}

		SmsInfo entry = getItem(pos);
		if(entry != null) {
			holder.tvNumber.setText(entry.getNumber());
			holder.tvContent.setText(entry.getContent());
		}

		return convertView;
	}

	static class ViewHolder {
		TextView tvNumber;
		TextView tvContent;
	}
}

3. SmsReceiver.java

package pete.android.study;

import java.util.ArrayList;
import java.util.List;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
import pete.android.study.SmsInfo;

public class SmsReceiver extends BroadcastReceiver {
	static ArrayList<SmsInfo> listSms = new ArrayList<SmsInfo>();
	@Override
	public void onReceive(Context context, Intent intent) {
		// get SMS map from intent
        Bundle extras = intent.getExtras();
        // a notification message
        String messages = "";
        if ( extras != null ) {
            // get array data from SMS
            Object[] smsExtra = (Object[]) extras.get( "pdus" ); // "pdus" is the key

            for ( int i = 0; i < smsExtra.length; ++i ) {
            	// get sms message
            	SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
            	// get content and number
            	String body = sms.getMessageBody();
            	String address = sms.getOriginatingAddress();
            	// create display message
            	messages += "SMS from " + address + " :\n";
            	messages += body + "\n";

            	// store in the list
                listSms.add(new SmsInfo(address, body));
            }

            // better check size before continue
            if(listSms.size() > 0) {
            	// notify new arriving message
            	Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
            	// set data to send
	            Intent data = new Intent(context, MainActivity.class);
	            // new activity
	            data.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

	            data.putParcelableArrayListExtra("ListSMS", listSms);
	            // start
	            context.startActivity(data);
            }
        }
    }
}

4. MainActivity.java

package pete.android.study;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends Activity {
    ListView mListData;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mListData = (ListView)findViewById(R.id.lvData);
        // receive list incoming messages
        ArrayList<SmsInfo> listSms = getIntent().getParcelableArrayListExtra("ListSMS");
        // check condition
        if(listSms != null && listSms.size() > 0) {
        	// set dat to list
        	SmsInfoAdapter adapter = new SmsInfoAdapter(this, listSms);
	        mListData.setAdapter(adapter);
        }
    }
}

E – Additional Config

We need to set uses-permission to receive SMS and register our SMSReceiver in order to make it work.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="pete.android.study"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />
	<uses-permission android:name="android.permission.RECEIVE_SMS" />

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

        <receiver android:name=".SmsReceiver">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

    </application>
</manifest>

F – Get the Sample Project by Pete

Click to browse Trunk from GoogleCode.

 

G – Final Words

– Hope you enjoy and learn something from this article 🙂

– Feel free to suggest, comment below!

 

Cheers,

Pete Houston

Advertisements

Playing with Toast message notification


Toast is very useful when you need to notify something to users and don’t require interactive responses.

One of the very basic toast like this:

Toast 01

Toast 01

public static void displayToast(Context c, String text, int duration) {
    Toast.makeText(c, text, duration).show();
}

By default, toast will stay close to the bottom of the screen.
If you want to set it in other location, just use setGravity() to define the location to display.

Toast 02

Toast 02

	public static void displayToast(Context c, String text, int duration, int gravity) {
		Toast t = Toast.makeText(c, text, duration);
		t.setGravity(gravity, 0, 0);
		t.show();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if(event.getAction() == MotionEvent.ACTION_DOWN) {
			QuickToast.displayToast(this, "A Toast in the center of the screen", Toast.LENGTH_LONG, Gravity.CENTER);
		}
		return super.onTouchEvent(event);
	}

It’s quite simple! However, in case you want to create a custom layout for toast, like an image, some texts…is it possible? The answer is Yes, and Yes!

This is a sample of a custom one:

Custom Toast

Custom Toast

	public static void displayToastFromResource(Context c, int duration, int gravity, ViewGroup parent) {
		// get layout inflater
		LayoutInflater inflater = LayoutInflater.from(c);
		// get the desired layout for toast
		View view = inflater.inflate(R.layout.layout_toast, parent);
		// get image view control
		ImageView ivIcon = (ImageView)view.findViewById(R.id.ivIcon);
		// set icon to image view
		ivIcon.setImageResource(R.drawable.icon);
		// get title text view
		TextView tvTitle = (TextView)view.findViewById(R.id.tvTitle);
		// set title content
		tvTitle.setText("I Love You");
		// get description text view
		TextView tvDesc = (TextView)view.findViewById(R.id.tvDesc);
		// set description content
		tvDesc.setText("It's been years since I met you !");

		// create toast from context
		Toast t = new Toast(c);
		// set center
		t.setGravity(Gravity.CENTER, 0, 0);
		// set display duration
		t.setDuration(duration);
		// set view layout to toast
		t.setView(view);
		// display toast message
		t.show();
	}

Oh well, you may wanna ask how I implemented those toast. It’s because I created a wrapper class QuickToast for handling toast settings and custom toasts.
This is the full source code I use for this tutorial:

1. QuickToast.java

package pete.android.study;

import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class QuickToast {
	public static void displayToast(Context c, String text, int duration) {
		Toast.makeText(c, text, duration).show();
	}

	public static void displayToast(Context c, int id, int duration) {
		Toast.makeText(c, id, duration).show();
	}

	public static void displayToast(Context c, String text, int duration, int gravity) {
		Toast t = Toast.makeText(c, text, duration);
		t.setGravity(gravity, 0, 0);
		t.show();
	}

	public static void displayToast(Context c, String text, int duration, int gravity, int[] offset) {
		Toast t = Toast.makeText(c, text, duration);
		t.setGravity(gravity, offset[0], offset[1]);
		t.show();
	}

	public static void displayToastFromResource(Context c, int duration, int gravity, ViewGroup parent) {
		// get layout inflater
		LayoutInflater inflater = LayoutInflater.from(c);
		// get the desired layout for toast
		View view = inflater.inflate(R.layout.layout_toast, parent);
		// get image view control
		ImageView ivIcon = (ImageView)view.findViewById(R.id.ivIcon);
		// set icon to image view
		ivIcon.setImageResource(R.drawable.icon);
		// get title text view
		TextView tvTitle = (TextView)view.findViewById(R.id.tvTitle);
		// set title content
		tvTitle.setText("I Love You");
		// get description text view
		TextView tvDesc = (TextView)view.findViewById(R.id.tvDesc);
		// set description content
		tvDesc.setText("It's been years since I met you !");

		// create toast from context
		Toast t = new Toast(c);
		// set center
		t.setGravity(Gravity.CENTER, 0, 0);
		// set display duration
		t.setDuration(duration);
		// set view layout to toast
		t.setView(view);
		// display toast message
		t.show();
	}
}

2. MainActivity.java

package pete.android.study;

import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.Toast;

public class MainActivity extends Activity  {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if(event.getAction() == MotionEvent.ACTION_DOWN) {
			QuickToast.displayToastFromResource(this, Toast.LENGTH_LONG, Gravity.CENTER, (ViewGroup)findViewById(R.id.llRoot));
		}
		return super.onTouchEvent(event);
	}
}

You can download full source code from one of these servers: Mediafire | Megaupload | Rapidshare | FreeFileHosting

 

Hope you enjoy it!

 

Cheers,

Pete Houston