woensdag 4 maart 2009

Developing with Android - day 1

I'm not a big gadget freak but being a java developer I just could not resist the temptation to buy the new HTC G1 android phone last month when it hit the stores. The idea of being able to develop my own mobile java applications and run them on G1 appealed to me. Also it seems the Open Handset Alliance seem pretty intent om making Android a big success. The idea of publishing a home-brewn app to the Android Market and making a fortune is of course a nice idea too :-)! But before we strike it rich we have to gain some experience with Android development.
Being currently 'inbetween projects' I can now luckily devote a few days entirely to discovering this new development platform. As it turns out there is some terminology to get used to but I managed to install and run my first android application on my phone in less than one day. So how did I do that?
My main sources of information are Google's android development site but even better is a Manning early access book called "Unlocking Android" which contains very specific examples and proved to be an excellent guideline. Most of the material presented in this post was found in Manning's book.

Preparing the environment
Following the instructions it's easy to install an eclipse plugin containing the android development environment including the emulator. I also made sure to include the android tools directory in my PATH environment variable.

The application
Just to get started I decided to write a reader for the Dutch news site called nu.nl. Quite a useless idea because nu.nl already offers both a mobile-ready version of their website at http://mobiel.nu.nl/pda/ and RSS feeds but what the heck, it will be a good exercise anyway.
We want the application to start with a screen displaying all news categories in a List (displayed to the left).
When pressing one of the categories/items in this list the app should display the most recent news items in this category. That should keep us busy for a day.

The main screen

So after creating a new Android project called NuDotNLReader with a main Activity called NuReader we can start implementing. An Activity basically is the same as one screen of your application and can be composed of various Views or ViewGroups. By default the main NuReader activity is created as a direct child of the generic Activity class. We want this screen to display a List so we change its inheritance like so:
public class NuReader extends ListActivity {

This class contains a static List of category names, for starters:
static final String[] CATEGORIES = new String[] {
"Algemeen", "Economie",
// more categories
}

and we use this list of category names to populate the main List screen at startup. Each ListActivity has an associated ListAdapter which contains the data to be displayed in the List:
setListAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, CATEGORIES));

The second argument to the ArrayAdapter constructor got me puzzled for a while. The first part android.R refers to the main resource class named 'R' which is created automatically for each new project in the same pacakge as the main Activity. It contains references to static information such as texts and images which are stored in binary format for storage and performance reasons. When you open up the source of R.java it contains a public static class layout but nowhere can we find any reference to simple_list_item_1. It turns out that this is one of several constants defined in the R.layout section by default that are just there for us to use.
This is already enough to make the main screen of the application work.
Next we want to make something happen when one of the categories in the List is clicked by the user. Let's override the onListItemClick method whose parameter 'position' tells us exactly which category in the List was selected. This category name can be passed on to the next Activity using the shared preferences available through the application context:

getApplicationContext()
.getSharedPreferences("nureader", Context.MODE_PRIVATE)
.edit()
.putString("category",
getListAdapter().getItem(position).toString())
.commit();
startActivity(new Intent(v.getContext(), CategoryReader.class));

Make sure to commit() the change to the shared preferences! By invoking startActivity with a new Intent for our next class CategroyReader, control will be passed on to this next Activity. It is also possible to receive some kind of return value from the next Activity by invoking startActivityForResult but we don't need this now.

Next up: the CategoryReader class, responsible for displaying the news items in a certain category. Since this is our first day we are going to make our life as easy as possible by just displaying the nu.nl category html page on a so called WebView. So the CategoryReader will just be a direct subclass of Activity with only one method, the onCreate method which is invoked each time the Activity is created:

public class CategoryReader extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String category = getApplicationContext()
.getSharedPreferences("nureader", Context.MODE_PRIVATE)
.getString("category", "empty");
WebView webview = new WebView(this);
webview.loadUrl(
"http://mobiel.nu.nl/pda/" + category.toLowerCase()+"/");
setContentView(webview);
}
}

In the onCreate we get the category name from the shared preferences in the application context. This category name is added to an URL which is fetched and displayed on a WebView element. A WebView element knows how to read and process HTML so it's basically a mini-browser element.

That's it!

Running the application on the G1 phone
As usual, getting an application onto the phone is astoundingly easy, once you know how to do it! First make sure you don't have the android emulator running. Connect your phone to an USB port and an USB icon appears at the top of the screen. Select 'Mount' to establish the link. Then
select Run as.. Android Application in eclipse and the application is 'automatically' installed on the phone and starts working instantly! Make sure to correctly disconnect the USB link before removing the USB cable.

Wrapup
So in just a few hours time it's possible to have at least a very small application running on your android mobile phone. Tomorrow we'll take a look at direct HTTP connections and how to asynchronously send and receive data from the nu.nl RSS feed.