User login



Syndicate content
Add to Google


PhoneFinder - SMS Phone Locator

SDK Version: 
M5

Introduction

In this tutorial we will create an application called PhoneFinder. This application will illustrate how to deal with sending and receiving SMS messages. The idea of the application is that when your phone is lost or stolen you will be able to use someone else's phone to retrieve the GPS coordinates at your phone's location to help you find it.

This application needs an Activity that will allow the user to enter in the password and an IntentReceiver that will be kicked off on incoming SMS messages.

Click here to download the complete source.

Password Entry

We will use the simple dialog shown below for password entry. Once the password is correctly entered we will save a MD5 sum of the password into the SharedPreferences for the package. The preferences is an easy way to save small amounts of persistent data. It is also only accessible by classes in your package. We will take the extra precaution of saving an MD5 of the password, this way if the data was read somehow it would not reveal the plain text password unless the password is very weak (aka in the dictionary).

The layout for this dialog, main.xml, is shown below:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:orientation="vertical"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     >
  7.  
  8.     <TextView
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         android:text="@string/password_label"
  12.         />
  13.     <EditText android:id="@+id/password"
  14.             android:maxLines="1"
  15.             android:layout_marginTop="2dip"
  16.             android:layout_width="wrap_content"
  17.             android:ems="25"
  18.             android:layout_height="wrap_content"
  19.             android:autoText="true"
  20.             android:scrollHorizontally="true"
  21.             android:password="true" />
  22.     <TextView
  23.         android:layout_width="fill_parent"
  24.         android:layout_height="wrap_content"
  25.         android:text="@string/password_confirm_label"
  26.         />
  27.     <EditText android:id="@+id/password_confirm"
  28.             android:maxLines="1"
  29.             android:layout_marginTop="2dip"
  30.             android:layout_width="wrap_content"
  31.             android:ems="25"
  32.             android:layout_height="wrap_content"
  33.             android:autoText="true"
  34.             android:scrollHorizontally="true"
  35.             android:password="true" />
  36.  
  37.     <Button android:id="@+id/ok"
  38.         android:layout_width="wrap_content"
  39.         android:layout_height="wrap_content"
  40.         android:layout_gravity="right"
  41.         android:text="@string/button_ok" />
  42.    
  43.     <TextView  android:id="@+id/text1"
  44.         android:layout_width="fill_parent"
  45.         android:layout_height="wrap_content"
  46.         />
  47. </LinearLayout>

As you can see it is a very simple layout, 2 text fields, 2 input fields, a button and another text field at the end to display messages to the user. The strings are defined in the strings.xml for better multilingual support.

The code for this activity is very simple. It's job is to make sure that the password is at least 6 characters, and that the 2 password fields match. Once that is confirmed then all we need to do is save the MD5 sum of the password the user entered into the SharedPreferences.

Here is the PhoneFinder Activity:

  1. public class PhoneFinder extends Activity {
  2.  
  3.     public static final String PASSWORD_PREF_KEY = "passwd";
  4.  
  5.     private TextView messages;
  6.     private EditText pass1;
  7.     private EditText pass2;
  8.  
  9.     @Override
  10.     public void onCreate(Bundle icicle) {
  11.         super.onCreate(icicle);
  12.         setContentView(R.layout.main);
  13.  
  14.         messages = (TextView) findViewById(R.id.text1);
  15.         pass1 = (EditText) findViewById(R.id.password);
  16.         pass2 = (EditText) findViewById(R.id.password_confirm);
  17.  
  18.         Button button = (Button) findViewById(R.id.ok);
  19.         button.setOnClickListener(clickListener);
  20.     }
  21.  
  22.     private OnClickListener clickListener = new OnClickListener() {
  23.  
  24.         public void onClick(View v) {
  25.             String p1 = pass1.getText().toString();
  26.             String p2 = pass2.getText().toString();
  27.  
  28.             if (p1.equals(p2)) {
  29.  
  30.                 if (p1.length() >= 6 || p2.length() >= 6) {
  31.  
  32.                     Editor passwdfile = getSharedPreferences(PhoneFinder.PASSWORD_PREF_KEY, 0).edit();
  33.                     String md5hash = getMd5Hash(p1);
  34.                     passwdfile.putString(PhoneFinder.PASSWORD_PREF_KEY,
  35.                             md5hash);
  36.                     passwdfile.commit();
  37.                     messages.setText("Password updated!");
  38.  
  39.                 } else
  40.                     messages.setText("Passwords must be at least 6 characters");
  41.  
  42.             } else {
  43.                 pass1.setText("");
  44.                 pass2.setText("");
  45.                 messages.setText("Passwords do not match");
  46.             }
  47.  
  48.         }
  49.  
  50.     };
  51. }

In onCreate() we initialize the various Views that we are using in the layout and then we setup the OnClickListener object for the "ok" button. When the "ok" button is pressed we are taken down into the onClick() function that starts on line 40.

In the onClick() function we confirm that the requirements for password length is met, and we make sure that both of the text boxes match. If that all happens then we get to line 48 where we setup the SharedPreferences.Editor class. This class allows us to edit the shared preferences for this application. It is called "shared" because it is application wide preferences, there are also Activty level preferences available via Activity.getPreferences(int).

Writing to the preferences is easy once you have the Editor object. You just use one of the putX() functions to add key/value pairs and then call the commit() function to save the results.

Then on line 48 you'll see that we call the member function getMd5Hash(String) which returns the MD5 sum as a string, and we store that in the preferences. Here is the getMd5Hash(String) function:

  1. public static String getMd5Hash(String input) {
  2.     try {
  3.         MessageDigest md = MessageDigest.getInstance("MD5");
  4.         byte[] messageDigest = md.digest(input.getBytes());
  5.         BigInteger number = new BigInteger(1,messageDigest);
  6.         String md5 = number.toString(16);
  7.        
  8.         while (md5.length() < 32)
  9.             md5 = "0" + md5;
  10.        
  11.         return md5;
  12.     } catch(NoSuchAlgorithmException e) {
  13.         Log.e("MD5", e.getMessage());
  14.         return null;
  15.     }
  16. }

We use a android.security.MessageDigest object passing in "MD5" as the algorithm we want to use. The digest() function is called passing in a Byte array from the String passed in, and it returns a byte array. This byte array can then be saved as a BigInteger and then converted to a hex string using toString(16). When we convert this byte array to a BigInteger leading zeros will be trimmed, so we add leading zeros with the while loop until the MD5 sum reaches 32 characters.

On the next page we will create the IntentReciever that will listen for SMS messages and respond to a relavent SMS message...

Comments

Submitted by blauesauser (not verified) on Mon, 05/12/2008 - 08:36.

I am waiting for Android phones to begin to developp on it

My french Blog on Android

http://gphone.news.free.fr

Submitted by Anonymous (not verified) on Thu, 03/20/2008 - 12:54.

Isn't there a way for the GPS or Wifi in another phone contact the GPS on your phone and track its location. even put it on a map.
Then you wouldn't need to send a text message and you could track it on a map.

How would this be done?

Submitted by hobbs on Thu, 03/20/2008 - 13:23.

Yeah, you could definitely do that using GTalk (XMPP) communication between the two phones and then putting the location on a Map with directions. It's outside the scope of this tutorial but would be a great feature!

Submitted by Anonymous (not verified) on Tue, 03/04/2008 - 01:33.

where is the sms stored in the receiving end?

Submitted by Anonymous (not verified) on Fri, 02/29/2008 - 00:29.

how to get the location name from my statusbar notifiacation and also how we know the service is currently running or not? and how to stop the service

Submitted by Anonymous (not verified) on Fri, 04/11/2008 - 05:53.

Api demo s there for starting and stopping of service......

Submitted by hobbs on Fri, 02/29/2008 - 11:20.

There is no service running, it's simply a listener that will be "woken up" whenever there is an SMS coming in.

Submitted by Jack Kwok (not verified) on Wed, 02/20/2008 - 00:05.

Thanks for the tutorial. Your app would be very useful if phone is ever lost or stolen. To make this app truly robust, I recommend having it auto-start whenever the app turns on. You will need to have the app listen for android.intent.action.BOOT_COMPLETED_ACTION

How about that?

Submitted by hobbs on Wed, 02/20/2008 - 11:19.

Not necessary because the Intent will be broadcasted everytime an SMS is sent, and the IntentReceiver will be woken up even if it's not running.

Submitted by joeflux on Wed, 12/26/2007 - 16:09.

After launching the application in the emulator, I try to send an SMS via the Emulator Control. But for some reason the Telephony Actions are grayed out(disabled). How can I fix this?

Submitted by hobbs on Wed, 12/26/2007 - 20:38.

Sometimes the emulator gets disconnected from Eclipse and you'll need to close the emulator and kill the "adb" process. Then try launching again. Also, some people have suggested using ddms to do this type of thing. DDMS can be started by executing the ddms command in the tools directory. Click here for some more information on eclipse and the emulator getting disconnected.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
Because you are not logged in, we must determine if you are a human or an Android designed to spam the internet. (Hint: All characters are lowercase)
                        _     
_ __ ___ _ _ | |__
| '_ \ / __| | | | | | '_ \
| | | | \__ \ | |_| | | | | |
|_| |_| |___/ \__,_| |_| |_|
Enter the code depicted in ASCII art style.