Building an Android app from the command line

Why build an Android App from the command line?

For the purpose of creating a continuous integration build of an Android app, I needed to be able to build the app and its dependent modules from the command line.  This is done using ant.

Prerequisites

Of course, you must have the appropriate Android SDK installed for your development platform.  Make sure the tools directory of the Android SDK is in your PATH.

You’ll also want to install ant.

If you don’t already have Java installed, then maybe you should go visit the Android Developer site for some important background information.

Your Project

If you created your project using IntelliJ, then the build files mentioned below should be created for you automatically. If you created your project using Eclipse, then you’ll have to take an extra step to create the build files. Simply cd into the root directory of your project and execute the android command to generate the build files:

$ cd android-project-directory
$ android update project --path .

This creates build.xml, default.properties, and local.properties for your project.

Important Files

There are four build files of critical importance which you can find in the root directory of your project:

build.xml — this is the main ant build script.  Check this file into your version control system.

default.properties — has a huge warning that says it’s generated by the Android tools and should not be modified. Check this file into your version control system.

ant.properties (optional) — allows you to add application-build-specific entries used by the build script. Typically empty for a straightforward Android app build but can be customized for non-standard directory structure or build dependencies.  Check this file into your version control system or omit it entirely from the project if you have no customizations or build dependencies.

local.properties — also generated by Android tools but should not be checked into your version control system. This is where the local path to your Android SDK directory root is specified, and this typically varies from one machine or build environment to the next.

Build Command

In order to build the app from the command line, cd to the root directory of your Android project (where the above files live and typically also where your src directory and your AndroidManifest.xml file live) and execute the ant command:

$ cd android-project-directory
$ ant clean debug

This command removes any leftover binaries or other artifacts from a previous build and rebuilds the app from scratch. If that is successful, then it packages and signs a debug version of the app. The console output from the command tells you where you can find the resulting .apk file for the app.  Here’s an example of the console output from a successful build showing the location of the resulting .apk file:

$ ant clean debug
Buildfile: /Users/mharper/Development/Android/Demo/HelloCI/build.xml
[setup] Android SDK Tools Revision 10
[setup] Project Target: Android 2.2
[setup] API level: 8
[setup]
[setup] ------------------
[setup] Resolving library dependencies:
[setup] No library dependencies.
[setup]
[setup] ------------------
[setup]
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup]
[setup] Importing rules file: tools/ant/main_rules.xml
clean:
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/bin
[delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/gen
...
compile:
[javac] Compiling 2 source files to /Users/mharper/Development/Android/Demo/HelloCI/bin/classes
...
debug:
[echo] Running zip align on final apk...
[echo] Debug Package: /Users/mharper/Development/Android/Demo/HelloCI/bin/HelloCI-debug.apk
BUILD SUCCESSFUL
Total time: 4 seconds

Building an App with Dependencies

It is common for an app to depend on one or more libraries that are built with a separate project. Thankfully, the Android build files make this easy to deal with.

Let’s say my HelloCI app depends on a HelloCILib that is a separate project built as an Android library.  Let’s also say that the HelloCI and HelloCILib root directories are in the same directory:

$ ls
HelloCI		HelloCILib

In order for the HelloCILib to be built before HelloCI, all you have to do is to reference its root directory path in the build.properties file of the main project (HelloCI, in this case) thusly:

android.library.reference.1=../HelloCILib

You can add more dependent projects simply by bumping the number at the end of the property, e. g. android.library.reference.2 etc. I understand that you should not leave any gaps in the numbering, however.

Notice how the build looks slightly different now that the dependent library is included:

$ ant clean debug
Buildfile: /Users/mharper/Development/Android/Demo/HelloCI/build.xml
    [setup] Android SDK Tools Revision 10
    [setup] Project Target: Android 2.2
    [setup] API level: 8
    [setup]
    [setup] ------------------
    [setup] Resolving library dependencies:
    [setup] /Users/mharper/Development/Android/Demo/HelloCI: ../HelloCILib => /Users/mharper/Development/Android/Demo/HelloCILib
    [setup] ------------------
    [setup] Ordered libraries:
    [setup] /Users/mharper/Development/Android/Demo/HelloCILib
    [setup] ------------------
    [setup]
    [setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
    [setup]
    [setup] Importing rules file: tools/ant/main_rules.xml
clean:
   [delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/bin
   [delete] Deleting directory /Users/mharper/Development/Android/Demo/HelloCI/gen
...
compile:
    [javac] Compiling 4 source files to /Users/mharper/Development/Android/Demo/HelloCI/bin/classes
...
debug:
     [echo] Running zip align on final apk...
     [echo] Debug Package: /Users/mharper/Development/Android/Demo/HelloCI/bin/com.standalonecode.HelloCI-debug.apk
BUILD SUCCESSFUL
Total time: 4 seconds

Summary

Building an Android app from the command line is very straightforward, especially if you have a standard Android app directory structure. All of this work is leading up to creating a continuous integration build under Jenkins at cloudbees.com which is the subject of another blog post.

The source for this example can be found on GitHub.

Android Emulator Seeks Network Connection

I wasted a good amount of time this morning due to the Android Emulator’s inability to be moved from one network to another.

Because it takes so damn long to startup, I typically keep the Android Emulator running when I am working on Circle 8 for Android (as I have been lately). In a typical day, I encounter at least three wifi networks: home, office, and the coffee shop.

Apparently, the Emulator prefers a monogamous relationship with networks and thus doesn’t switch over to a new wifi connection. I was trying to setup the Email app in the Emulator to connect to my email account and it failed over and over again. I finally decided to restart the Emulator, thinking that maybe it was lost with respect to the network. Sure enough, restarting the Emulator resulted in being able to browse to a web page as well as setup the Email app no problem.

Edit (August 2011):

I have since abandoned the Emulator in favor of developing directly to an Android device. Significantly snappier and less prone to bizarre errors.