Thursday, January 22, 2009

Developing Android without Eclipse or Ant

The Android documentation recommends using Eclipse for development, but this is sluggish on my laptop, and feels cluttered on compact screens. A stated alternative is to use Ant, but this is also unnecessary as the build commands it invokes can be easily extracted and executed manually. This suits my preference for a minimalistic or practically non-existent IDE, especially on laptops, as well as my distaste for editing XML. As a bonus, on Ubuntu, I install one package:

$ sudo apt-get install sun-java6-jdk

along with the Android SDK and I'm ready to develop for Android. In contrast, the Ant package has several dependencies, and the required version of Eclipse is newer than the currently available Ubuntu package.

Here are the details:

$ SDKDIR=~/android-sdk-linux_x86-1.0_r2 # Where I extracted the SDK.
$ PATH=$SDKDIR/tools:$PATH
$ activitycreator -o somepath some.project.name
$ cd somepath

At this point Ant can build the project, but masochists like me will prefer to shun Ant and run the underlying commands themselves. The following command generates R.java from the resources:

$ aapt p -m -J src -M AndroidManifest.xml -S res -I $SDKDIR/android.jar

Next, the source is compiled to .class files. This is why we need the JDK:

$ mkdir bin/classes
$ javac -encoding ascii -target 1.5 -d bin/classes \
-bootclasspath $SDKDIR/android.jar src/some/project/*
# When libs exist, append -classpath=libs/*.jar

These files contain instructions for the JVM. They are converted to Dalvik bytecode via:

$ dx --dex --output=bin/classes.dex bin/classes # If libs exist, append libs/*.jar

The resources and assets are packaged:

$ aapt p -f -M AndroidManifest.xml -S res -I $SDKDIR/android.jar -F bin/projectname.ap_
# When assets exist, add -A assets

This package is itself packaged with the Dalvik bytecode to make the final product:

$ apkbuilder bin/something.apk -z bin/projectname.ap_ -f bin/classes.dex -rf src -rj libs
# Use -u for unsigned builds.

Now if I could only roll my own Dalvik compiler for a language I like, I could avoid the Java SDK, as well as Java itself.

Sunday, January 4, 2009

Encoding videos for the G1

Soon after Android's debut, initial reviews were complaining about the G1's inability to play videos. At the time I felt it was a trifling matter. Since YouTube already works on the G1, a more general video player ought to require only minor tinkering. And why is it a big deal anyway? Are people in a rush to experience Hollywood blockbusters on a tiny screen and tinny speakers?

Sure enough, video playing apps appeared quickly on Android Market. I found at least three in my last search. As for their utility: now that I've played with them, I understand why some see a video player as a must-have, and not merely yet another vehicle for demonstrating the G1's capabilities.

While breathtaking cinematography, award-winning soundtracks and state-of-the-art special effects translate poorly to a handheld device, movies that derive their strength chiefly from factors such as a witty dialogue lose little. Informational clips are another good use case. And even with scenes that only work well with a big screen: if they're my favourite scenes of all time, it's still comforting to have them at my fingertips, even if they are greatly reduced.

Which leaves the problem of converting videos to a G1-friendly format. I knew almost nothing about the black art of video encoding, but after hours of false starts and trawling the net for help, I still know almost nothing. However, I picked up enough to get started.

An unofficial FAQ states the G1 currently supports the H.264, 3GP and MPEG4 video codecs. I skimmed a few Wikipedia entries to decode this alphanumeric soup, and my interpretation is that this really means the G1 recognizes .MP4 and .3GP files (which are container formats and not video encoding methods) and understands the H.263, MPEG-4 ASP ("roughly similar" to H.263) and H.264 (aka MPEG-4 AVC) video compression standards. [Trivia: ASP expands to the somewhat oxymoronic "Advanced Simple Profile".]

The G1 only speaks the BP (Baseline Profile) dialect of H.264; videos that use more advanced features of H.264 play incorrectly, or not at all. [At last this post makes sense to me!]

On Ubuntu, the easiest way to encode videos was to use avidemux (sudo apt-get install avidemux). For audio, I only tested the AAC codec (usually at 96kbps), but several others should also work. For video, selecting MPEG-4 ASP produced videos that seemed to tax the CPU heavily on playback, often to the point of unwatchability. Perhaps this could be remedied by lowering the number of frames per second via an appropriate filter.

In any case, I prefer selecting the MPEG-4 AVC video codec and dumbing it down for the G1 by disabling the appropriate H.264 options: I changed the Max Consecutive B-Frames to 0, unchecked all options related to B-frames, and disabled CABAC along with the 8x8 Transform and 8x8 Intra search options. As before, I added the MPlayer variant of the resize filter: the G1 has a 480x320 screen in landscape mode. At 384kbps, this produced videos that played smoothly though higher bit rates should be feasible.

Now that I appreciate video more, I eagerly await the "Cupcake" Android update which is rumored to have video recording. I also hope the next generation of hardware will have video out and enough power to handle any popular codec.

Saturday, January 3, 2009

G1 Miscellany

What fortuitous timing! Intending to start from a clean slate, I performed a factory reset on my G1 recently. I had forgotten that, unlike the Developer Edition of the G1, even an unlocked standard issue G1 requires a SIM card with a data plan for the initial setup.

I was going to wait until I could borrow a suitable SIM from a friend for a few seconds (as after registration, I'm happy to use just WiFi for my G1 net needs for the time being), but I just heard about a new jailbreak for all G1s. It works by flashing the G1 back to RC29 where the old jailbreak can be exploited. Once done, one can register the G1 via WiFi, without a data plan or even a SIM.

Some Linux-specific notes. The G1 is touchy about the SD card for the RC29 image. The time it worked for me, I had reformatted it with "mkfs -t vfat /dev/foo", and used uppercase exclusively for the filename. To get the "adb" tool from the Android SDK working, I had to create an appropriate /etc configuration file.

I only needed two of the incantations. On the G1, I enabled adb via:
<enter>setprop persist.service.adb.enable 1<enter>

and once in the adb shell, I opened the Settings menu before registration:
$ am start -a android.intent.action.MAIN -n com.android.settings/.Settings

From here it was trivial to setup WiFi and sign in.

Some unrelated tips. When typing, Alt + Delete clears the whole line. RemoteDroid turns the G1 into a wireless keyboard and mouse; a fun application to show off.

I remain easily amused by the digital compass. The Orienteer app is often the first app I demonstrate. Also, the Sky Map app is perfect for those interested in picking out constellations in the night sky, but not interested enough to actually memorize them and figure out when and where they can be seen.