Test Ride
The Android SDK is a free 80-MB download (code.google.com/android/documentation.html). The preferred developer toolset is Eclipse 3.3 (Europa), which also requires the JDT plug-in, Java Development Kit (JDK) 5 or 6, and optionally the Web Services Tool (WST).
I installed the software on a Dell Latitude with a 2.4-GHz Mobile Pentium 4 CPU equipped with 512 MB of RAM. The SDK documentation has a step-by-step procedure for installing the necessary software and getting the requisite "Hello World!" sample Android application up and running. The integration between the Eclipse IDE and the Dalvik emulator that implements the Android environment and executes your Android application code is very good.
Because I'm always dealing with software rocket science, an application that moved a rocket around the screen seemed an ideal project to explore Android's features and quirks. Google's example Android code was a trove of information. I borrowed some code from its Lunar Lander game and other examples to get started.
To write Android applications, you extend an Activity and add code that implements your design (as in Java ME). You soon appreciate onCreate(),
where you can place initialization code with error recovery. This is also where you create an instance of a View
that manages your application's window with its UI.
However, you can't do much with a View
until you understand how to use Android's XML layout file to create the visual objects and interactive widgets that are children of the View
. This layout file contains custom XML tagged elements that represent widgets buttons, text-entry boxes, and labels. Because placement of widgets and the flow of events among them is hierarchical, by nesting the order of the XML tags, you arrange the screen layout and the position of its widgets. The XML is saved into a file in the res/layout/ directory. When you build the Android application, it compiles the layout file's XML elements into resources that you reference by ID number.
To create its UI, the Activity first assigns its visual content to a View
that uses your XML file. Then it makes an instance of the View
, using ID numbers to obtain the appropriate widget resources that comprise the layout. Android's use of XML to organize the UI layout lets youwithin limitstinker with the interface without modifying code in the View
. It would be nice to have a visual editor that gave you a better idea of how changes to the XML nesting affects the UI's layout.
I made a simple layout that filled the screen and presented a background image. Using Blender3D, I took the 3D model of the Dr. Dobb's
rocket that I used for a previous article (www.ddj.com/mobile/193104855) and rendered it into a 2D PNG bitmap image. Processing key presses with Android's key event handlers felt similar to those in a MIDlet, where only the method names and some arguments had changed. It didn't take long to have a rocket scooting around the screen. The program, SpaceActivity, is available online at www.ddj.com/code/.
One Android shift that tripped me up was getting the screen's sizevalues that are often crucial when designing a program's gameplay. In a MIDlet's constructor, you simply called getWidth()
and getHeight()
for this information. Calling the same methods in Android's View
constructor always retrieved values of zero. The reason is that View
doesn't know how the screen is oriented (which affects the View
's dimensions) until onStart()
makes it visible. When this occurs, Android immediately invokes an onSizeChanged()
method. This method provides values for the screen's visible dimensions in its new orientation. You override this method when you want to force the View
to redraw the screen for the new orientation, but for my application I just grabbed the height and width values. Listing One compares how to determine the mobile phone's screen dimensions in Java ME and Android.
Listing One
(a) Java ME
class DrawScreen extends Canvas implements CommandListener { private int width; private int height; DrawScreen() { // Constructor width = getWidth(); height = get Height(); }
(b) Android
<br> class SpaceView extends View { public SpaceView(Context context, AttributeSet attrs, Map inflateParams) { super(context, attrs, inflateParams); } // constructor // This method called at startup or when screen changes. // w, h,-- current screen's width and height // oldw, oldh -- previous screen's width and height @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mX = w; // Get screen's width mY = h; // Get screen's height } // onSizeChanged
My second programming test was to port over a basic Java ME scribbling program that uses the touchscreen. The Java ME program starts by displaying a blank image. When you touch and draw on the screen with a stylus, the program draws a colored line that tracks the stylus. The MIDlet uses pointerPressed(),
pointerDragged(),
and pointerRelease()
to implement the tracking/drawing operations. A key press paints the image buffer with white, erasing it.
The first difference for porting to Android was writing an XML layout file to support the View
's generation of a UI window. The second difference was managing the Bitmap
object that both stored and displayed the results of the scribbling. I overrode the onSizeChanged()
method so that if the screen's orientation changed, a new Bitmap
would be allocated. Also, to guarantee that work of art you're creating is safely preserved when another application seizes the foreground, I added code to the onFreeze()
method to save the Bitmap
into a Bundle, termed an "icicle."
The third difference was that Android uses one lone method, onTouchEvent(),
to handle all touchscreen interactions. Fortunately, you can easily break out the types of stylus actionsdown, up, and dragwith a switch
statement. I used the switch
statement to call slightly modified pointerPressed(),
pointerDragged(),
and pointerRelease()
methods. Although onTouchEvent()
places all motion events into an array where you can replay the entire track of the pointer's path, the original pointerDragged()
worked by capturing the new point and drawing a line to the previous point, which it had saved previously. The behavior worked the first time in Android. The only changes I made were to how colors were assigned to the event. See Listing Two online for a comparison between the Java ME and Android touch-screen code. The original Java ME program, Simple_Scribble, and the Android application, ScribbleActivity, are also available online.
Lessons Learned And Looking Forward
If you have Java ME experience, you will have a gentle learning curve when writing Android code. Most of what comprises the curve is determining what classes have familiar methods, and learning Android's quirks. Using XML for screen layout, which reduces the edit-build-execute cycles to tweak the UI to look right, is a big plus. Android, like the iPhone, has the potential to change the way we work with mobile phonesmaybe even make all of their features useful.
Tom is the head of Proactive Support for embedded products at Freescale Semiconductor. He has written documentation of demo programs for several mobile APIs. He can be reached at [email protected].