Tuesday, December 02, 2008

G1 Camera Tricks

The G1's camera seems to be slow. Really slow. As in several-seconds slow. I always wondered why; then I started to look at my pictures from the Macy's Thanksgiving Day Parade.

Ah. I see. I don't think that's because of the curvature of the lens (it's not curved THAT much) I was apparently panning the camera when I took this picture (to keep up with the float, though I didn't correctly account for the very long shutter delay, and the float ended up behind the pole). You are seeing the effect of the CCD "scanning". This reminds me of this project, in which a dude builds a digital camera from a flatbed scanner. This is a picture of his garage door opening and closing while he takes a single exposure.

I hope this isn't an actual limitation of the G1's hardware. My cheap Nokia 6267, a feature phone, had an excellent 2MP camera that took pictures nearly instantaneously. So far, the G1's camera reminds me of my short experience with Windows Mobile 5's camera app - slow and clunky.

Using a Horizontal Progress Bar in Android

I was working on my Android downloader application yesterday, when I ran into a bit of a snag. I wanted to display a list of downloads (similar to the Firefox downloads window). Each item in the list should show the file name and a horizontal progress bar. I started to implement this, and several hours later stumbled upon the arcane solution. I wanted to share this, both to help anybody who may be trying to do something similar, and also to illustrate how the lack of good documentation is hurting aspiring Android developers.

I thought that I could put a ProgressBar instance in my xml, set it to be indeterminate, give it a max and a value, and be done. However, it wasn't nearly that easy. After a few hours of hunting on Google and the Android Groups, I stumbled upon the solution in an online preview of The Busy Coder's Guide to Android Development. In short, I had to set the following on my ProgressBar's XML:

style="?android:attr/progressBarStyleHorizontal"
WTF?

Let's try to break this down. The ? on the front indicates that this is a reference to something in the current theme. What is a theme? Well, Android's UI infrastructure is similar to Swing or HTML in that it tries to accommodate components whose size is not known until runtime. Android's components are also themeable (similar to the Swing Synth LAF). A theme is a collection of related component styles. You can control the theme used by your application in the AndroidManifest.xml file. So, I think we can safely conclude that attr/progressBarStyleHorizontal is something whose actual value is defined in a particular theme.

If you take a peek in the android source code, inside frameworks/base/core/res/res/values/attrs.xml, you will find the following definition:

<resources>
<declare-styleable name="Theme">
<!-- snip -->
<attr name="progressBarStyleHorizontal" format="reference" />
OK, not very useful. However, in frameworks/base/core/res/res/values/themes.xml, we find:
<resources>
<style name="Theme">
<item name="progressBarStyleHorizontal">@android:style/Widget.ProgressBar.Horizontal</item>
Nowe we're getting somewhere. Finally, inside frameworks/base/core/res/res/values/styles.xml, we see:
<resources>
<style name="Widget.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
<item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
</style>

What's going on here? Well, it looks like themes.xml defines a theme as a collection of styles. Along with that, styles.xml specifies a set of attributes that should be applied to a particular XML element. By saying

<ProgressBar style="?android:attr/progressBarStyleHorizontal">
we are really saying
<ProgressBar style="@android:style/Widget.ProgressBar.Horizontal">
which is like saying
<ProgressBar 
android:indeterminateOnly="false"
android:progressDrawable="@android:drawable/progress_horizontal"
android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"
android:minHeight="20dip"
android:maxHeight="20dip">
Spiffy.

For bonus points, we can look in frameworks/base/core/res/res/drawable/progress_horizontal.xml. This file apparently contains the declarative expression of the horizontal scrollbar graphic. I don't know how extensive this syntax is, but a quick peek at progress_indeterminate_horizontal.xml indicates that it is possible to specify animations in this XML file format.

All this seems really powerful, only somewhat useful, and totally confusing. All I wanted was to create a horizontal progress bar. I can't tell why the Android widget collection includes only one ProgressBar class that is meant to be used for horizontal, indeterminate horizontal, indeterminate circular, and every other kind of possible progress indicator. Perhaps there would be duplication of code if those were separated into different classes. Whatever. I actually don't mind that they stuffed all those progress indicators into a single class. There are some questionable decisions (like having both indeterminate and indeterminateOnly), but I can deal with it. On the other hand, the incantations that you have to use to get the Progress Bar to behave are truly arcane. I think I have proven in this blog post that there is some method to the madness and, as is often the case, easy access to the source code is a must. What bothers me most is that there was absolutely no documentation on the subject. Google seems silent on this topic, and even The Busy Coder's Guide mentions that the style attribute won't be covered until a later edition of the book (though it is possible that the Google Books sample chapter is out of date at this point).

I still maintain that Android is one of the most unique application systems that I've seen. However, as I've tried to develop for it, I have encountered a general lack of polish. Many things that you want to do as a developer are confusing and poorly documented. Familiarity with existing technologies (such as Swing or Applet programming) is pretty much useless here. On the other hand, the core concepts (such as the use of Intents to start applications and communicate between processes, the HEAVY use of message passing, and the declarative nature of the AndroidManifest.xml file) seem to be an excellent base upon which to build not just an open operating system, but a truly open user experience. A power user can really replace virtually any aspect of the system. Perhaps developers will create third party libraries that make Android a little easier within which to develop, or maybe Google itself will provide simpler interfaces for developers. Or perhaps Android will die out because developers had a difficult time building anything particularly complex. Whatever the outcome, I'm excited for the ride.