Getting Down and Dirty with Google’s Android

ust a few weeks ago, the Open Handset Alliance pushed its baby “Android” out into the spotlight. While no devices available on the market run it, Google has offered 10 million dollars in prize money to the developers who create the most compelling applications. The code exposed in this article isn’t going to win any of that money on its own, but perhaps it can get you started towards your own Android application. After you finish this article, you’ll understand the basics of setting up the SDK, displaying text using the XML layout schema, getting the device’s location from the GPS component, and finally rendering your own text with a custom view implementation.

Getting Setup
The code for this article was written on Mac OS X with Eclipse. Since Android ships with a plug-in for Eclipse it seemed the natural choice for a get-to-know-you article. Your mileage may vary. If you want to follow along directly with this article you can start by grabbing the following software:

If you’re using a different SDK, go ahead and skip down to the next section.

To get started, install Eclipse, then get the Android SDK and install the plug-in with the directions linked above. Creating an Android project should now be as simple as clicking “New” in the file menu. Traditionally, new languages are first demonstrated with the help of a “Hello World” application. But, since “Hello World” is so last decade, we’ll focus on something a little more interesting like “Hello World: Here I am.” Along the way, we’ll talk about custom vs. XML-driven views, GPS, and a few of the differences between other SDKs and Android.

Activities
Every mobile environment has its foundation class. J2ME applications have midlets, BREW has applets, and Android uses activities. The activity provides you with basic access to the phone’s OS and events. It will contain your base constructor, key handler, suspend/resume functionality, and other low-level hand-set access. Your app, in essence, will be an extension of the Activity class. Here’s how our sample application’s Activity looked before we cluttered it up with functionality:

public class LocateMe extends Activity {	public void onCreate(Bundle params) 	{    	super.onCreate(params);    	setContentView(R.layout.main);	}	public boolean onKeyDown(int keyCode, KeyEvent event)     	{		return true;	}}

The onCreate function will be called when your application is started for the first time. The bundle object contains basic information including any launch parameters or environment data needed on startup. Activities can be full screen or floating, they can be nested but each is a semi-autonomous unit. What, you might ask, is setContentView?

The “View”
The View class is Android’s super-class for nearly all screen rendering; there are several varieties. Each view has a rectangle it’s responsible for drawing on. That rectangle can be defined and extended in a myriad of ways. For the sake of expediency this article will only cover two major players: Custom Views and Android’s XML content views. Since the basic project, upon creation, starts with a pre-defined “Hello World” XML view, that seems a natural place to start.

If you snoop around in a new Android project, at some point you’ll find a file called main.xml. This file, through a simple XML schema, describes a screen layout to Android. Here’s what our sample application’s main.xml looks like:

While this seems relatively straightforward, let’s go over it anyway. This particular file defines a relative layout, which means all the elements are described by their relation to one-another or to their parent. As with Views, there are several layout methods but we’ll stick to this one for the sake of clarity.

The RealtiveLayout listed above contains one text element which is set to fill its parent (your LocateMe activity.) The LocateMe activity is full screen by default, so the text element will inherit that property and the text will appear in the top left corner of the screen. Additionally, a reference number must be set for the XML file so that Android can find it from your source code. By default, these reference numbers are stored in R.java and will look something like this:

public final class R { 	 public static final class layout 	{	        public static final int main=0x7f030001;    	}}

Views may be nested so, unlike in J2ME, it’s possible to mix custom views with the Widgets released by the Android team. In J2ME, developers were forced to choose between a GameCanvas and J2ME’s application canvas. This meant that if you wanted a custom look, you’d have to roll all your own widgets on top of the GameCanvas. Not so with Android; view types can be mixed and matched in code with ease. Android also comes with a widget library (built on top of the View class) for scrollbars, text-entry, progress-bars, and many more. These standard widgets can be overloaded and customized at the whim of your UI team. Now that you’ve a few building blocks in place, it’s time to get into the sample application.

Android in Action
This demonstration application will display the user’s current latitude and longitude in text form. The constructor onCreate will be identical to the first listing we covered, except you’ll add a bunch of code to the key handler. Now, onKeyDown will look like this:

public boolean onKeyDown(int keyCode, KeyEvent event) {	   	//Head out if we're loading or if it isn't the select key   	if(keyCode != KeyEvent.KEYCODE_DPAD_CENTER || m_bLoading)   	{   		return true;   	}   	   	//Flip the loading bit so we don't start this again.   	m_bLoading = true;   	   	getLocation();   	   	return true;}

Let’s break this down. First, the code checks to make sure the correct key has been struck and that it hasn’t started this process already, as you only want to call getLocation() once. Then, it will flip the loading flag and call into getLocation(). Here’s the getLocation function:

private void getLocation(){	Location loc;	LocationManager locMan;	LocationProvider locPro;	List proList;	//Show "Loading" on the screen.	setContentView(R.layout.laoding);					//Get the location manager from the server	locMan = (LocationManager) getSystemService(LOCATION_SERVICE); 	proList = locMan.getProviders();		//Just grab the first member of the list. It's name will be "gps"	locPro = proList.get(0);	loc = locMan.getCurrentLocation(locPro.getName());	Lat =  (float)loc.getLatitude();	Lon =  (float)loc.getLongitude();	CreateView();	setContentView(customView);}

This is where things start getting a little more interesting. Sadly, Google’s documentation on this subject is not overly helpful. After the variable declarations, you’ll want to display some loading information. R.layout.loading corresponds to another simple XML layout View. A simple setContentView() call will paint the screen with the loading message.

Author’s Note: At compile time, Android pre-packs all XML layout data. If you want to change layout properties after compile, as it stands now, you’ll have to do it programmatically.

The only method for obtaining a LocationManager is through a getSystemService() call. With a LocationManager in hand, it’s possible to get a list of location providers. On an actual handset this list could contain several GPS services. In reality, you’d want to be more selective about which provider you use based on power consumption, accuracy, and the availability of additional services. For now, the emulator provides a sample path through San Francisco. Custom GPS files can be uploaded for location based testing, consult the documentation here for more information. While more complicated and nuanced methods exist for testing and emulating location-based services, using the default path through San Francisco will work just fine for the sake of this simple application.

With a location Manager and a location provider, it’s now possible to make the actual getCurrentLocation call. This returns a snapshot of the phone’s current position in the form of a Location object. With this in hand, you can get the latitude and longitude. Methods for retrieving such information are available in the documentation. Now, with the location of the virtual handset, you can get into the final piece of this sample application: creating and displaying a custom view.

Using Custom Views
In its most simplistic form, a View in Android must overload only one function onDraw(). Custom Views can be complicated 3D playback implementations or they can be ultra simplistic text rendering. Here’s what the CreateView function listed above looks like:

public void CreateView(){	customView = new CustomView(this);}

This function simply evokes the constructor for the CustomView object. The definition of which follows below:

public class CustomView extends View{	LocateMe overlord;   	   	public CustomView(LocateMe pCtx)   	{   		super(pCtx);   		overlord = pCtx;   	}   	public void onDraw(Canvas cvs)   	{   		Paint p = new Paint();   		String sLat = "Latitude: " + overlord.getLat();   		String sLon = "Longitude: " + overlord.getLon();   		cvs.drawText(sLat , 32, 32, p);   		cvs.drawText(sLon, 32, 44, p);   	}   	}

This custom Android view renders the latitude and longitude test data to the screen in text. It requires a pointer to LocateMe, the Activity extender that is the heart of this application. Its two methods are the constructor and the onDraw methods. The constructor evokes the super-class constructor and stashes off the Activity pointer. onDraw will create a new Paint object (an object that encapsulates color, transparency, and other basic theme information) which will access the default color theme. From there, it’s a matter of setting up the display strings, and drawing them to the screen using the Canvas pointer. For those of you who know something about J2ME’s game canvas, this should look very familiar.

The Waiting Game
From purely a development standpoint, Android is a very powerful SDK. It combines XML layout schemes with custom view rendering and in house scrollbar, maps, and other in house widgets. All which can be overloaded and customized on the whim of a developer. Its documentation is rough; there are missing features and gaps in functionality (like SMS interop and a clear monetization plan), but overall Android looks very promising for what even Google acknowledges is a “First Look” SDK. Now we’ll just have to see if anyone actually deploys a phone that uses it.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: