Android: First Impressions.

by Robert Cooper

I want to talk a little about Android. I am very much going to sidestep the holy war about is it or isn't it Java, except to say, this looks a lot like something that would have been derived from the Danger stack. The commonalities are striking. As a Sidekick owner, I am terribly pleased with "Java-ish" development for that platform, and I think seeing something similar in wide deployment is great. That said...


First, lets talk about the Android UI API. I recall last year at Sun Tech Days,"The Gos" was asked what, in retrospect he would do different with Java. The first thing he came up with was the Swing API. The "747 Cockpit" feel of the API is overwhelming to new users. Frankly, Android takes this to a whole new level. Just look at the JavaDoc for the Checkbox class:


Constants inherited from class android.view.View
Fields inherited from class android.view.View

Public Constructors

          CheckBox(Context context)
          CheckBox(Context context, AttributeSet attrs, Map inflateParams)
          CheckBox(Context context, AttributeSet attrs, Map inflateParams, int defStyle)
Methods inherited from class android.widget.CompoundButton
Methods inherited from class android.widget.Button
Methods inherited from class android.widget.TextView
Methods inherited from class android.view.View
Methods inherited from class java.lang.Object
Methods inherited from interface android.view.KeyEvent.Callback
Methods inherited from interface android.graphics.drawable.Drawable.Callback




Now, it certainly makes sense for everything to extend View, but View has a helluva lot of stuff on it. I am pretty sure my Checkbox doesn't need scroll setting, for instance. There are also things like getDrawingRectangle() that seem like they would be better served with internal implementation to a Painter, rather than everything right there.

There is also a dearth of Interfaces to mark functionality. For example, the MenuBuilder.ItemImpl. Notice the crossover with both View and Compound button above.

Public Methods

        int  getGroup()

Return the ordering group of this menu item.
        int  getId()

Return the identifier for this menu item.
        Intent  getIntent()

Return the Intent associated with this item.
        int  getShortcutAlphabeticKey()

Return the key for this menu item's alphabetic shortcut.
        int  getShortcutAlphabeticModifier()

Return the modifiers of this menu item's alphabetic shortcut key.
        int  getShortcutNumericKey()

Return the key for this menu item's numeric (12-key) shortcut.
        SubMenu  getSubMenu()

Get the sub-menu to be invoked when this item is selected, if it has one.
        CharSequence  getTitle()

Retrieve the current label text of the item.
    final    View  getView()
        boolean  hasSubMenu()

Check whether this item has an associated sub-menu.
        void  invoke()
        boolean  isCheckable()

Return whether the item can currently display a check mark.
        boolean  isChecked()

Return whether the item is currently displaying a check mark.
        boolean  isFocused()
        boolean  isSelected()
        boolean  isSeparator()

Check whether this is a separator item.
        boolean  isShown()

Return the shown state of the menu item.
        void  sendSelectionChange(boolean selected)
        void  setAlphabeticShortcut(int modifier, int alphaKey)

Change the alphabetic shortcut associated with this item.
        void  setCallback(Runnable callback)
        void  setCheckable(boolean checkable)

Control whether this item can display a check mark.
        void  setChecked(boolean checked)

Control whether this item is shown with a check mark.
        void  setClickListener(OnClickListener clickListener)

Set a custom listener for invokation of this menu item.
        void  setIntent(Intent intent)

Change the Intent associated with this item.
        void  setNumericShortcut(int numberKey)

Change the numeric shortcut associated with this item.
        void  setSelected(boolean selected)
        void  setSelectionListener(OnSelectionListener selectionListener)

Set a custom listener for selection changes of this menu item
        void  setShortcut(int numberKey, int modifier, int alphaKey)

Change both the numeric and alphabetic shortcut associated with this item.
        void  setShown(boolean shown)

Return the shown state of the menu item.
        void  setTitle(CharSequence title)

Change the label text associated with this item.
Methods inherited from class java.lang.Object
Methods inherited from interface android.view.Menu.Item



Just having marker interfaces for things that support Focus, Check, etc would really help clean some of this up from a API standpoint. Now, getting around some of this Cockpit feel should be easy, since Android includes a declarative XML UI system out of the box.

Now maybe I am just missing something here, but:

<?xml version="1.0" encoding="utf-8"?>
<!-- Demonstrates using a relative layout to create a form -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/blue"
android:padding="10px">

<TextView id="@+id/label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Type here:"/>

<EditText id="@+id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_below="@id/label"/>

<Button id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignParentRight="true"
android:layout_marginLeft="10px"
android:text="OK" />

<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeft="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
</RelativeLayout>


There seem to be a few shortcomins here. The schema URL doesn't seem to resolve to anything meaningful. It *seems* to me, and I could be wrong here, that there is no way to use non-Android provided widgets in your UI. Compare this to the forthcoming GWT declarative UI XML:

<!-- Note how we add a new namespace for the application's package -->
<app:ButtonTree
 
xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'
 
xmlns:app='http://code.google.com/webtoolkit/com.example.myapp.client'
/><g:Tree xmlns:g='http://code.google.com/webtoolkit/com.google.gwt.user.client.ui'>
 
<g:TreeItem>
   
<g:Button>Do something</g:Button>
 
</g:TreeItem>
</g:Tree>

Here the namespace maps to a package, making it easy to build UIs with other components. Another thing that stands out about the declarative UI stuff is the lack of CSS. While the Android UI lets you specify design elements in:


The following values are supported for dimensions (described in TypedValue):

  • px (pixels)
  • dip (device independent pixels)
  • sp (scaled pixels — best for text size)
  • pt (points)
  • in (inches)
  • mm (millimeters)


Which is great. However, it seems like rather than specifying margins, paddings, alignments, etc, in the XML files, being able to define these in a CSS, or CSS-like file would seem like a better idea. Then, even, allow me to specify different CSS files based on different device UI types: screen size/aspect ratio, portrait vs landscape mode, etc. This has always been one of the failings of mobile development as long as I can remember.

So that summarizes what I don't like. What I do like is the great separation of functionality into Intents, Activities and Views. To summarize this, you can expose functionality of your application, or use the Android base functionality, by invoking Intents. These intents can then launch something else, or not if the phone won't do that, or the needed software isn't there. These can take you to Activities. Activities are single screen-type states in your application with a managed lifecycle. Activities then reference Views with a clear binding pattern, and a suspend-resore lifecycle that lets not just your whole application, but sub-elements of your application (List Buddies, Chat Window, Add Buddy individually) be suspended out of the running state and navigated around. Honestly, it makes me feel better about some of my own API design, I have GWT APIs in Gwittir that look very similar. :)

While I haven't spent a great deal of time with it yet, there are a few things that stand out as big points of pain in the current developer tooling. There is no way to toy around with the LocationManager class in a real way because the emulator just doesn't have a way to alter this information at runtime. It is also really complicated to mock out the ApplicationContext class for unit testing your code -- which seems very un-Google. While Android is easily one of the most documented new systems I have recently -- maybe ever -- seen, approaching the docs the first time is terribly imposing. John Lombardo at LinuxDevices.com has a great intro and guide to the guides.

1 Comments

hamada elnopy
2007-11-20 14:09:28
i have played with android a litte
its look like bulding a rcp for eclipse constants every where with a strange programnig model,and
thier mplementation of the mvc model is strange
try to provide a data mode for the list component
then it supposed to ask another enttity about the view of that model object. but it was strange that i found the method to get the view for the model object in the model it self ,which mean that i cant have many views for the same model.