Moazzam’s Ramblings

6Apr/100

Setting up your Android environment

I have seen quite a few posts on some lists asking about how to set up a programming environment for Android. While it is very straight forward, the documentation is all over the place. So, I decided to write this tutorial :) .

In this tutorial, we will install Android SDK in eclipse (Galileo), we will add an SD Card to your emulator and put some pictures in it. I have written this tutorial with Windows users in mind but the process should not be very different for other platforms.

I have written this tutorial assuming that you already have JDK installed. If you don't have it already installed then please install it before reading this. You can find a tutorial on how to install here.

Installing the SDK

  1. Download the latest eclipse IDE from
    http://www.eclipse.org/downloads/.

    You can also download Galileo directly from here.

  2. Create a folder in your c:\ drive and name it android. The file you just downloaded (at least from the direct link I provided above) is a zip file which contains a folder called eclipse. Extract the zip file and place the folder in, c:\android. Now, you have eclipse installed in c:\android. Go into the eclipse folder. You will see an executable called eclipse. Double click it to run eclipse.
    Click to enlarge

    Click to enlarge

  3. Now, download the android SDK 1.6 (the latest as of this writing) for windows from the link below:http://developer.android.com/sdk/download.html?v=android-sdk-windows-1.6_r1.zipTo download the SDK for other platforms, go here :http://developer.android.com/sdk/1.6_r1/index.html
  4. Extract the contents of the zip file in c:\android\. Now, you will have 2 folders in c:\android\. One is eclipse and the other is android-sdk-windows-xxx.android-sdk-windows-xxx folder contains another folder called tools. We need to add this folder to the system's PATH variable. To do that, Click on Start, then right click on "My Computer" and click on "Properties" in the menu that pops up.

The "System Properties" dialog will pop up. Click on the "Advanced" tab and then click on "Environment variables". Another dialog will appear.

Run eclipse. Click on Help -> Install New Software.

Click to enlarge

Click to enlarge

An install dialog will appear. Click on "Add", another dialog will appear. Type in Android for name and put in https://dl-ssl.google.com/android/eclipse for Location. Then click OK. Click on next, check both the checkboxes and click next. Eclipse will start downloading the plugin and install it. You will be asked to restart eclipse after the installation is done. Click on "Yes" when it asks you to restart. Eclipse will restart and you can, now, create Android projects!

Click to enlarge

Click to enlarge

Now that the basic installation is done. Let's setup the SC Card.

Setting up the SD Card

Creating the SD card is very easy.

  1. Click on Start -> Run. The run dialog will appear
  2. Type "cmd" (without the quotes) and hit enter or click the OK button. A commant prompt window will appear.
  3. Type "android list targets" in it and hit enter. It will show you a list of targets. Get the id for Android 1.6. It will most probably be 2
  4. Type the command "android create avd -n testavd -t <target_id> -c 128M" (without the quotes) and hit enter. Make sure to subsitute the <target_id> with the actual ID you got from "android list targets" command. Since it will most probably be 2, the command will look like this "android create avd -n testavd -t 2 -c 128M (again without quotes).
  5. Press enter 1 more time

Viola! you have created your SD Card for the emulator. The next time you start the emulator, you will be able to access it. Below is an illustration to make things easy.

Click to enlarge

Click to enlarge

When I created my SD card, I needed to get some pictures on it. So, I used an external program called winimage to do that.

Working with your SD card

  1. Download winimage from http://www.winimage.com/download.htm. You can either get the zip file or the exe file. I downloaded the zip file, extracted it and use that.
  2. Run winimage.exe and make sure your emulator is not running.
  3. Click on Open image icon. Browse to c:\android\sd_card\ folder. Select sdcard and click OK button. Winimage will open the sdcard image. Now, you can browse the file structure and add files, delete files, etc. After you are done, make sure to close winimage or you won't be able to access the SD card from the emulator.

As always here's an illustration:

Click to enlarge

Click to enlarge

Now, we have an the SD Card image open. Let's create a folder called "media" and put some pictures in it. When you take pictures with your phone's camera they are stored in the media folder in  your SD Card.

To create the media folder, click on Image, then on Create Folder. A dialog box will appear. Type "MEDIA" in it. and Click OK. After the folder is created, you can drag and drop pictures from your computer to the media folder just like you would normally do it when copying files from one location on your computer to another.

WinImage

Click to Enlarge

Create Folder

Click to enlarge

Copy pictures

Click to enlarge

18Nov/099

Android HttpRequest class (version 2.1)

Version of of this class had some bugs so I corrected them and here is the latest version :)

Enjoy!

package moz.http;
 
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.http.client.HttpClient;
import org.apache.commons.*;
import android.util.Log;
/**
* HTTP Request class
*
* You can use this class and distribute it as long as you give proper credit
* and place and leave this notice intact :). Check my blog for updated
* version(s) of this class (http://moazzam-khan.com)
*
* Usage Examples:
*
* Get Request
* --------------------------------
* HttpData data = HttpRequest.get("http://example.com/index.php?user=hello");
* System.out.println(data.content);
*
* Post Request
* --------------------------------
* HttpData data = HttpRequest.post("http://xyz.com", "var1=val&var2=val2");
* System.out.println(data.content);
* Enumeration<String> keys = dat.cookies.keys(); // cookies
* while (keys.hasMoreElements()) {
* 		System.out.println(keys.nextElement() + " = " +
* 				data.cookies.get(keys.nextElement() + "rn");
*	}
* Enumeration<String> keys = dat.headers.keys(); // headers
* while (keys.hasMoreElements()) {
* 		System.out.println(keys.nextElement() + " = " +
* 				data.headers.get(keys.nextElement() + "rn");
*	}
*
* Upload a file
* --------------------------------
* ArrayList<File> files = new ArrayList();
* files.add(new File("/etc/someFile"));
* files.add(new File("/home/user/anotherFile"));
*
* Hashtable<String, String> ht = new Hashtable<String, String>();
* ht.put("var1", "val1");
*
* HttpData data = HttpRequest.post("http://xyz.com", ht, files);
* System.out.println(data.content);
*
* @author Moazzam Khan
*/
public class HttpRequest {
 
        /**
        * HttpGet request
        *
        * @param sUrl
        * @return
        */
        public static HttpData get(String sUrl) {
                HttpData ret = new HttpData();
                String str;
                StringBuffer buff = new StringBuffer();
                try {
                        URL url = new URL(sUrl);
                        URLConnection con = url.openConnection();
 
                        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                        while ((str = in.readLine()) != null) {
                                buff.append(str);
                        }
                        ret.content = buff.toString();
                        //get headers
                        Map<String, List<String>> headers = con.getHeaderFields();
                        Set<Entry<String, List<String>>> hKeys = headers.entrySet();
                        for (Iterator<Entry<String, List<String>>> i = hKeys.iterator(); i.hasNext();) {
                                Entry<String, List<String>> m = i.next();
 
                                Log.w("HEADER_KEY", m.getKey() + "");
                                ret.headers.put(m.getKey(), m.getValue().toString());
                                if (m.getKey().equals("set-cookie"))
                                ret.cookies.put(m.getKey(), m.getValue().toString());
                        }
                } catch (Exception e) {
                        Log.e("HttpRequest", e.toString());
                }
                return ret;
        }
 
 
 
 
        /**
        * HTTP post request
        *
        * @param sUrl
        * @param ht
        * @return
        * @throws Exception
        */
        public static HttpData post(String sUrl, Hashtable<String, String> ht) throws Exception {
                String key;
                StringBuffer data = new StringBuffer();
                Enumeration<String> keys = ht.keys();
                while (keys.hasMoreElements()) {
                        key = keys.nextElement();
                        data.append(URLEncoder.encode(key, "UTF-8"));
                        data.append("=");
                        data.append(URLEncoder.encode(ht.get(key), "UTF-8"));
                        data.append("&amp;");
                }
                return HttpRequest.post(sUrl, data.toString());
        }
        /**
        * HTTP post request
        *
        * @param sUrl
        * @param data
        * @return
        */
        public static HttpData post(String sUrl, String data) {
                StringBuffer ret = new StringBuffer();
                HttpData dat = new HttpData();
                String header;
                try {
                        // Send data
                        URL url = new URL(sUrl);
                        URLConnection conn = url.openConnection();
                        conn.setDoOutput(true);
                        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
                        wr.write(data);
                        wr.flush();
 
                        // Get the response
 
                        Map<String, List<String>> headers = conn.getHeaderFields();
                        Set<Entry<String, List<String>>> hKeys = headers.entrySet();
                        for (Iterator<Entry<String, List<String>>> i = hKeys.iterator(); i.hasNext();) {
                                Entry<String, List<String>> m = i.next();
 
                                Log.w("HEADER_KEY", m.getKey() + "");
                                dat.headers.put(m.getKey(), m.getValue().toString());
                                if (m.getKey().equals("set-cookie"))
                                dat.cookies.put(m.getKey(), m.getValue().toString());
                        }
                        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                        String line;
                        while ((line = rd.readLine()) != null) {
                                ret.append(line);
                        }
                        Log.e("ERROR", line);
                        wr.close();
                        rd.close();
                } catch (Exception e) {
                        Log.e("ERROR", "ERROR IN CODE:"+e.getMessage());
                }
                dat.content = ret.toString();
                return dat;
        }
        /**
        * Post request (upload files)
        * @param sUrl
        * @param files
        * @return HttpData
        */
        public static HttpData post(String sUrl, ArrayList<File> files)
        {
                Hashtable<String, String> ht = new Hashtable<String, String>();
                return HttpRequest.post(sUrl, ht, files);
        }
        /**
        * Post request (upload files)
        * @param sUrl
        * @param params Form data
        * @param files
        * @return
        */
        public static HttpData post(String sUrl, Hashtable<String, String> params, ArrayList<File> files) {
                HttpData ret = new HttpData();
                try {
                        String boundary = "*****************************************";
                        String newLine = "rn";
                        int bytesAvailable;
                        int bufferSize;
                        int maxBufferSize = 4096;
                        int bytesRead;
 
                        URL url = new URL(sUrl);
                        HttpURLConnection con = (HttpURLConnection) url.openConnection();
                        con.setDoInput(true);
                        con.setDoOutput(true);
                        con.setUseCaches(false);
                        con.setRequestMethod("POST");
                        con.setRequestProperty("Connection", "Keep-Alive");
                        con.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
                        DataOutputStream dos = new DataOutputStream(con.getOutputStream());
 
                        //dos.writeChars(params);
 
                        //upload files
                        for (int i=0; i<files.size(); i++) {
                                Log.i("HREQ", i+"");
                                FileInputStream fis = new FileInputStream(files.get(i));
                                dos.writeBytes("--" + boundary + newLine);
                                dos.writeBytes("Content-Disposition: form-data; "
                                + "name="file_"+i+"";filename=""
                                + files.get(i).getPath() +""" + newLine + newLine);
                                bytesAvailable = fis.available();
                                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                byte[] buffer = new byte[bufferSize];
                                bytesRead = fis.read(buffer, 0, bufferSize);
                                while (bytesRead > 0) {
                                        dos.write(buffer, 0, bufferSize);
                                        bytesAvailable = fis.available();
                                        bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                        bytesRead = fis.read(buffer, 0, bufferSize);
                                }
                                dos.writeBytes(newLine);
                                dos.writeBytes("--" + boundary + "--" + newLine);
                                fis.close();
                        }
                        // Now write the data
 
                        Enumeration keys = params.keys();
                        String key, val;
                        while (keys.hasMoreElements()) {
                                key = keys.nextElement().toString();
                                val = params.get(key);
                                dos.writeBytes("--" + boundary + newLine);
                                dos.writeBytes("Content-Disposition: form-data;name=""
                                + key+""" + newLine + newLine + val);
                                dos.writeBytes(newLine);
                                dos.writeBytes("--" + boundary + "--" + newLine);
 
                        }
                        dos.flush();
 
                        BufferedReader rd = new BufferedReader(
                        new InputStreamReader(con.getInputStream()));
                        String line;
                        while ((line = rd.readLine()) != null) {
                                ret.content += line + "rn";
                        }
                        //get headers
                        Map<String, List<String>> headers = con.getHeaderFields();
                        Set<Entry<String, List<String>>> hKeys = headers.entrySet();
                        for (Iterator<Entry<String, List<String>>> i = hKeys.iterator(); i.hasNext();) {
                                Entry<String, List<String>> m = i.next();
 
                                Log.w("HEADER_KEY", m.getKey() + "");
                                ret.headers.put(m.getKey(), m.getValue().toString());
                                if (m.getKey().equals("set-cookie"))
                                ret.cookies.put(m.getKey(), m.getValue().toString());
                        }
                        dos.close();
                        rd.close();
                } catch (MalformedURLException me) {
 
                } catch (IOException ie) {
 
                } catch (Exception e) {
                        Log.e("HREQ", "Exception: "+e.toString());
                }
                return ret;
        }
}

You will also need the class below:

package moz.http;
import java.util.Hashtable;
public class HttpData {
      public String content;
      public Hashtable cookies = new Hashtable();
      public Hashtable headers = new Hashtable();
}
15Oct/094

HTTP Request class for Android (version 2)

Hi Everyone,

After some people pointed out the problems they had with version 2 of this class, I took it all out.  Please go to: http://moazzam-khan.com/blog/?p=490 for version 2.1

2Sep/093

HTTP Request class for Android

Here is a class that can be used to make HTTP get and HTTP post requests. I haven't commented everything but the usage should be pretty clear from the method signatures.

Note: This is for Android 1.5.

[java]
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.http.client.HttpClient;

import org.apache.commons.*;
import android.util.Log;

public class HttpRequest {

/**
* HttpGet - doesn't read cookies
*
* @param sUrl
* @return
*/
public static HttpData get(String sUrl) {
HttpData ret = new HttpData();
String str;
StringBuffer buff = new StringBuffer();
try {
URL url = new URL(sUrl);

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
while ((str = in.readLine()) != null) {
buff.append(str);
}
ret.content = buff.toString();
} catch (Exception e) {
Log.e("HttpRequest", e.toString());
}
return ret;
}

/**
* HTTP post request
*
* @param sUrl
* @param ht
* @return
* @throws Exception
*/
public static HttpData post(String sUrl, Hashtable ht) throws Exception {
StringBuffer data = new StringBuffer();
Enumeration keys = ht.keys();
while (keys.hasMoreElements()) {
data.append(URLEncoder.encode(keys.nextElement(), "UTF-8"));
data.append("=");
data.append(URLEncoder.encode(ht.get(keys.nextElement()), "UTF-8"));
data.append("&");
}
return HttpRequest.post(sUrl, data.toString());
}
/**
* HTTP post request
*
* @param sUrl
* @param data
* @return
*/
public static HttpData post(String sUrl, String data) {
StringBuffer ret = new StringBuffer();
HttpData dat = new HttpData();
String header;
try {
// Send data
URL url = new URL(sUrl);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();

// Get the response

Map> headers = conn.getHeaderFields();
Set>> hKeys = headers.entrySet();
for (Iterator>> i = hKeys.iterator(); i.hasNext();) {
Entry> m = i.next();

Log.w("HEADER_KEY", m.getKey() + "");
dat.headers.put(m.getKey(), m.getValue().toString());
if (m.getKey().equals("set-cookie"))
dat.cookies.put(m.getKey(), m.getValue().toString());
}
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
ret.append(line);
}

wr.close();
rd.close();
} catch (Exception e) {
Log.e("ERROR", "ERROR IN CODE:"+e.toString());
}
dat.content = ret.toString();
return dat;
}
}
[/java]

You will also need this class along with it.

[java]

import java.util.Hashtable;

public class HttpData {
public String content;
public Hashtable cookies = new Hashtable();
public Hashtable headers = new Hashtable();
}
[/java]

11May/090

Android 1.5 SDK Released !

Google has released Android 1.5 SDK. This release is based on the cupcake branch in Android's repository. Cupcake was a modified version of the SDK written by a group of independent developers and functioned better than the 1.0 SDK. Android 1.5 SDK also has other enchancements like a better profiler. For a list of all changes and enhancements, please visit: http://developer.android.com/sdk/RELEASENOTES.html

22Apr/090

Sending data to other activities in Android

Let's say you have a list activity which lists some information and you have another activity which adds/edits information in the list. How do you tell the edit activity which item (in the list of the first activity) needs to be edited? 

 

In the first activity, you will do this :

/*********************************************
* These constants will be passed to the second activity and
* the second activity will return this back when it returns its
* result
**********************************************/
private static final int ALERT_ADD = 100;
private static final int ALERT_EDIT = 110;
 
public void callAddEditActivity() {
	// get the unique ID of the selected
	long itemId = this.getListView().getSelectedItemId();
 
	/** If no item was selected, then this condition will be true */
	if (itemId == ListView.INVALID_ROW_ID) {
		//put an alert here asking to select something
		return;
	}
	/**************************************************
	* Now, we will get the position of the item in the list. From that
	* we can get the cursor object, which will contain other information
	* about it. In this case, I want to get the name  and phone number.
	*
	* The cursor object is a regular cursor you use with a database.
	* Refer to my post about using databases with Android for more
	* information on it.
	***************************************************/
	int pos  = this.getListView().getSelectedItemPosition();
	Cursor c = (Cursor) this.getListView().getAdapter().getItem(pos);
 
	/***************************************************
	* Now, you can create a "bundle" which can be passed to setCotntact.
	* SetContact is the other activity which is used for adding/editing
	* names and phone numbers. It will use the bundle to get the data
	* for the item it is supposed to edit.
	****************************************************/
 
	Intent in1  = new Intent();
	Bundle bun = new Bundle();
 
	bun.putLong("id", c.getLong(3));
	bun.putString("name", c.getString(0));
	bun.putString("phone", c.getString(1));
	in1.setClass(this, SetContact.class);
	in1.putExtras(bun);
 
	startActivityForResult(in1, ALERT_EDIT);
}

Let's take a look at SetContact activity which be used to edit (or add) data to the list.

package gContact.gContact;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
 
public class SetContact extends Activity {
	private EditText txtName;
	private EditText txtPhone;
	private long id;
 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		/** This piece is not important */
		super.onCreate(savedInstanceState);
		setContentView(R.layout.set_contact);
		txtName = (EditText) findViewById(R.id.alertText);
		txtPhone = (DatePicker) findViewById(R.id.alertDate);
 
		/********************************************
		* When data is passed to any activity in a bundle, it can be
		* accessed through getExtras(). If nothing is passed, then this
		* bundle will be null.
		*
		* If the bundle is null, then that means we are adding a new item
		* otherwise we are editing an existing item
		*********************************************/
		Bundle bun = getIntent().getExtras();
		if (null == bun) return;
 
		/*********************************************
		* If this is an edit, then set the proper values in the text boxes
		**********************************************/
		this.id     = bun.getLong("id");
		String text = bun.getString("name");
		String phone = bun.getString("phone");
 
		if (null != text) txtName.setText(text);
		if (null != phone) txtPhone.setText(phone);
	}
 
	/*****************************************
	* This creates a menu with 2 buttons  - save and cancel
	******************************************/
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuItem item1 = menu.add(0, 0, 0,"Save");
		MenuItem item2 = menu.add(0, 1, 1, "Cancel");
		return true;
	}
 
	/*********************************************
	* This function is run when one of our menu items is selected.
	**********************************************/
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		/**************************************
		*  If Save was clicked/pressed/tapped then we
		* gather name and phone number and pass it to the
		* main activity so it can add it to the database.
		*
		* Adding to the database can be done here too, but
		* I like doing it in the main activity
		***************************************/
		case 0:
			Bundle conData = new Bundle();
			String name = txtName.getText().toString();
			String phone = txtPhone.getText().toString();
 
			conData.putString("name", name);
			conData.putString("phone", phone);
			conData.putLong("id", this.id);
 
			Intent mIntent = new Intent();
			mIntent.putExtras(alertData);
			setResult(RESULT_OK, mIntent);
			break;
 
		case 1: // Cancel
			break;
		}
		finish();
		return true;
	}
}

When the second activity sends data back to the first activity, onActivityResult method is called (in the first activity). It will look something like this :

protected void onActivityResult(int requestCode, int resultCode, Intent data){
	switch (requestCode) {
	case ALERT_ADD:
		if (resultCode != RESULT_CANCELED) {
			Bundle res = data.getExtras();
 
			/***********************************************
			* After we get the new information from the second activity, we
			* can add it to the database and then refresh the list. If the below
			* statement is unclear, refer to my blog post on databases and
			* Android
			************************************************/
			db.createContact(
				res.getString("name"),
				res.getString("phone")
			);
			fillData();
		}
		break;
 
	case ALERT_EDIT:
		if (resultCode != RESULT_CANCELED) {
			Bundle res = data.getExtras();
			db.updateContact(res.getLong("id"), res.getString("name"), res.getString("phone"));
			fillData();
		}
		break;
	}
}
18Mar/091

More Android phones on the way

Yes, you heard it. More Android based phones (at least 2)are on their way some time in 2009. Motorola, Sony, Samsung, etc are also going to come out with Android phones some time by 2010. HTC's CEO said that they will be releasing at least 3 phones this year. We know one of them is the G2, which means that HTC will be releasing 2 more Android phones. 

For those of you who are thinking of buying an Android based phone: you may want to wait a few more months and see if the new phones are better than G1 (which has an annoying design honestly)

Here is some more information on this topic :

Information week

Beta news

Engadget


24Jan/090

Android Exeda – A more detailed look

I had written a post about CompuLab releasing an Android based phone called Exeda. It's official now and they are making it available in March. They will make the price available along with the phone. It has a 3.5 inch screen which is sun-readable. It also has a touchpad which acts as a mouse. The phone itself seems very small in the picture so it might not be meant for big fingers. The keys are very small in size. It also comes with Windows Mobile and they say they will add support for Linux in the future (yay! Linux).

According to its maker

"Exeda is designed to serve as an enterprise digital assistant (EDA). Comprised of embedded components, the exeda has guaranteed long-term availability and can be custom configured when ordered in volume. "

For more information go to http://www.exedamobile.com/web/?gclid=CJHqrvG4qJgCFQrAGgodLyYvnw and http://www.exedamobile.com/web/index.php?option=com_content&view=article&id=3&Itemid=7

Exeda

Exeda

Exeda

Exeda

21Jan/090

A new Android/Windows Mobile phone

I found this on Russian site of AndroidTeam(androidteam.ru) that a company called Compulab is going to release a new phone called Exada which will run both Android and Windows Mobile. This phone will provide left and right click capability. It will provide a large number of control keys (buttons) and has an ethernet port. I wonder if that is supposed to be a replacement for USB or if it's a regular ethernet port.  Below is the picture of the phone :

Exada

Exada

5Jan/095

Android and Alarms

Since I joined the Android user groups, there have been a lot of questions about 2 things - databases and alarms. I have already written a post about how to use a database in Android and in this one, I will talk about how to use Alarms. If there are any other topics you would like to see a tutorial on, please feel free to let me know. You can leave your requests in the comments section. Oh, and this post (like previous posts) is for Android 1.0.

Alarms in Android are not used in a conventional way. When your application sets an alarm, it's just telling that alarm service to wake it up at a certain time. The user won't hear any sounds and the phone won't vibrate (unless your application plays a sound or makes the phone vibrate after it wakes up). Alarms will work if the device goes to sleep but they are cleared if the device is turned off or restarted. So, you will need to set the alarm again if you want it to "go off" even after a device re-boot.

Our receiver class will be called "AReceiver" (without the quotes, of course). In the manifest file, we will add this line (which is in bold below):

<application android:icon="@drawable/icon5" android:label="@string/app_name">
<activity android:name=".SomeApp" 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="AReceiver" android:process=":remote" />

Now, that the alarm receiver is set, lets take a look at the class that will set and cancel the alarms:

package SomeApp.SomeApp;

import java.util.Calendar;

import java.lang.String;

import android.app.AlarmManager;
import android.app.ListActivity;
import android.app.PendingIntent;
import android.os.Bundle;
import android.util.Log;

import android.content.Intent;
import android.widget.Toast;

/**
 * When this code is run only one alert will be displayed even though 2 alerts were
 * were setup (as one of them will be cancelled later on
 */
public class SomeApp extends ListActivity {
	/* for logging - see my tutorial on debuggin Android apps for more detail */
	private static final String TAG = "SomeApp "; 

	protected Toast mToast; 

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

		Calendar cal = Calendar.getInstance();

		Intent intent        = new Intent(SomeApp.this, AReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(this, 1234567, intent, 0);
		PendingIntent sende2 = PendingIntent.getBroadcast(this, 123123, intent, 0);

		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis()+30000, sender); // to be alerted 30 seconds from now
		am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis()+15000, sende2); // to be alerted 15 seconds from now

		/* To show how alarms are cancelled we will create a new 		Intent and a new PendingIntent with the
	 	* same requestCode as the PendingIntent alarm we want to cancel. In this case, it is 1234567.
         	* Note: The intent and PendingIntent have to be the same as the ones used to create the alarms.
         	*/
		Intent intent1        = new Intent(SomeApp.this, AReceiver.class);
		PendingIntent sender1 = PendingIntent.getBroadcast(this, 1234567, intent1, 0);
		AlarmManager am1 = (AlarmManager) getSystemService(ALARM_SERVICE);
		am1.cancel(sender1);

        } catch (Exception e) {
        	Log.e(TAG, "ERROR IN CODE:"+e.toString());
        }
    }

}

You will notice that this is only a "one-shot" alarm. If you want to set a repeating alarm, it is explained in Android's documentation. However, I will write on that too if there is demand for it. Now, let's examine the code. For setting an alarm, you will need 4 things:

  • The class that's setting the alarm
  • The class that will be called when the alarm "goes off"
  • The time at which the alarm should go off
  • A requestCode (which will use as a unique ID to identify the alarms) used in PendingIntent.

For cancelling an alarm, you need 3 things:

  • The class that set the alarm
  • The class that was to be called when the alarm "goes off"
  • The requestCode you used for PendingIntent object.

We have covered 2 things - the declaration of the receiver in our manifest file and the class that sets and cancels alarms. Now, we need to look at the class that will be called when the alarm goes off.

package someApp.someApp;

import java.util.Calendar;

import android.content.Context;
import android.content.BroadcastReceiver;
import android.util.Log;
import android.widget.Toast;

/** All receiver classes must extend BroadcastReceiver */
public class AReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context con, Intent in) {
		try {
			/* Display an alert */
			Toast.makeText(con, "hello my jello ", Toast.LENGTH_LONG).show();
		} catch (Exception r) {
			Toast.makeText(con, "You were supposed to do something"
					+" now but I can't retrieve what it was.",
					Toast.LENGTH_SHORT).show();
			Log.e("ALARM_RECEIVER", r.toString());
		}
	}
}