a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Setting Up An Android Project Build

As the owner of a G1 I’ve played around at several times in the past with simple Android application development. The SDK tools and introductory documentation provided by Google make it easy to get started. Before embarking on a more serious project, however, I decided to figure out how to set up projects in a systematic way that allows for both development and reliable scripted builds (e.g. for continuous integration). Creating a project layout and build that works takes a few steps and tweaks, not all of which are covered in the documentation I found, so I thought I’d walk through my approach to it for those that are interested.

Goals

My goals for this project setup were as follows:

  • Support for development in Eclipse using the ADT. Although Eclipse is not my first choice of IDE, it is decent enough and compelling when combined with the ADT tooling.
  • Support for building from the command-line, with no dependency on an IDE.
  • The ability to run tests on a device (or emulator) using the SDK testing and instrumentation support.
  • Containment of all components within a single directory which can be easily versioned.

This all seems like it should be simple: the Android SDK has support for Eclipse, Ant builds, and testing. However, putting it all together can take some work, because not all the pieces play together as nicely as you might hope. First of all, although it is easy to create either an Eclipse project or an Ant one (and both cases are well documented), I would like both. I experimented with two methods: creating an Eclipse project either before or after setting up the Ant build. In my experience adding an Eclipse project to an existing Ant build proved more troublesome, and more difficult to debug if there was an issue. So I recommend starting by setting up your projects (application and test) in Eclipse first.

Setting Up the Eclipse Projects

Select File > New > Project, and choose Android Project in the dialog:

Fill in your Project, Application, Package and Activity names:

Click Next, then check the box to Create a Test Project. So that both projects live under simple, single root directory, uncheck the Use default location box, and specify the location as the “test” subdirectory of your main application’s directory:

Click Finish and the easy part is done: you should have two new projects in your workspace, with the test project nested neatly within the main one1. If you list the contents of your application’s directory, you should see something like:

jsankey@caligula:~$ ls -a1 work/my-app/
.
..
AndroidManifest.xml
assets
bin
.classpath
default.properties
gen
.project
res
.settings
src
test

Likewise, the test subdirectory should contain:

jsankey@caligula:~$ ls -a1 work/my-app/test
.
..
AndroidManifest.xml
assets
bin
.classpath
default.properties
gen
.project
res
.settings
src

Adding a Simple Test Case

At this point, it’s worth adding a simple test case to your test project as a starting point. This will allow you to experiment with the Eclipse setup and (forthcoming) Ant builds. To do this, navigate to your test project and select File > New > Class. To actually utilise the instrumentation support in the test project, have your test class extend android.test.ActivityInstrumentationTestCase2:

You’ll need to fill in the generic type parameter for this class, add a constructor, and add a simple test case:

package com.zutubi.android.myapp.test;

import com.zutubi.android.myapp.MyAppActivity;

import android.test.ActivityInstrumentationTestCase2;

public class MyAppActivityTest extends ActivityInstrumentationTestCase2<MyAppActivity> {

	public MyAppActivityTest() {
		super("com.zutubi.android.myapp", MyAppActivity.class);
	}

	public void testSanity() {
		assertEquals(2, 1 + 1);
	}
}

To try it out, select Run > Run As > Android JUnit Test and choose (or start) a device. If the universe is in working order, the test should pass!

Adding Ant Builds

To add standard Android Ant builds to the existing projects, I used the android command line tool from the SDK. Firstly, I added a build to the main application using android update project:

jsankey@caligula:~$ cd /home/jsankey/work/my-app
jsankey@caligula:~/work/my-app$ android update project -p .
Updated local.properties
Added file ./build.xml
It seems that there are sub-projects. If you want to update them
please use the --subprojects parameter.

As the output suggests, this command adds an Ant build.xml file to your project, and a local.properties file that stores the location of the Android SDK. Notice that the tool has picked up the fact that there is a test/ subdirectory with another project in it. However, do not be tempted to take its advice to run with the –subprojects flag: this will treat your test project as a regular project. Instead, change into the test/ subdirectory and run android update test-project:

jsankey@caligula:~/work/my-app$ cd test
jsankey@caligula:~/work/my-app/test$ android update test-project -p . -m ..
Resolved location of main project to: /home/jsankey/work/my-app
Updated default.properties
Updated local.properties
Added file ./build.xml
Updated build.properties

Again, the build.xml and local.properties files are added, although this time the build file will contain test rules. Notice that the relative path to the main project is passed using the -m flag. You can see the effect of this in the created build.properties file, which sets the value of tested.project.dir.

At this point you can build the project and run the tests from the command line. First ensure that you have only one device available (e.g. one emulator running), then, in the test/ subdirectory where we left off, run ant run-tests:

jsankey@caligula:~/work/my-app/test$ ant run-tests
... clipped several lines of output ...
run-tests:
     [echo] Running tests ...
     [exec] 
     [exec] com.zutubi.android.myapp.test.MyAppActivityTest:.
     [exec] Test results for InstrumentationTestRunner=.
     [exec] Time: 0.158
     [exec] 
     [exec] OK (1 test)
     [exec] 
     [exec] 

BUILD SUCCESSFUL
Total time: 10 seconds

Excellent: now we have the build and test working with both Eclipse and Ant (or so it seems…).

Separating the Output Directories

Although on the surface our two methods of building appear to work, once you start working in this environment you will notice problems. Most likely, you will start to see errors showing up in your Eclipse build (or the Android Console) after builds from the command line. By default both the Eclipse and Ant builds use the same folders for generated source (gen/) and output (bin/), which causes this conflict. The Eclipse project does not react well to changes that occur underneath it.

To solve this problem, we can force the two different builds to use different output locations. The Ant build makes it easy to override both the generated source and output locations, using gen.dir and out.dir properties. The best place to set these properties is in the build.properties file for each of the projects:

out.dir=build
gen.dir=build/gen

Note that you will need to create build.properties for your main project (your test project should already have one). I chose to put the gen/ directory used by Ant under the output directory just to tidy things up a little.

This should be all that is required, however, thanks to a bug in the default Ant rules, if you customise the output directory your test project will not find the output of your main project to build against. To fix this, you need to edit test/build.xml, and add the line:

<property name="extensible.classpath" value="${tested.project.absolute.dir}/${out.dir}/classes"/>

just before the closing </project> tag. This assumes your test and main projects have the same out.dir, which although slightly lazy is a simpler than loading the main project’s properties to get its out.dir (and a sane assumption in my book).

You can make sure everything works by doing clean builds using Ant:

jsankey@caligula:~/work/my-app/test$ cd ..
jsankey@caligula:~/work/my-app$ ant clean
Buildfile: build.xml
    [setup] Android SDK Tools Revision 6
    [setup] Project Target: Android 2.2
    [setup] API level: 8
    [setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
    [setup] Importing rules file: platforms/android-8/ant/ant_rules_r2.xml

clean:
   [delete] Deleting directory /home/jsankey/work/my-app/build
   [delete] Deleting directory /home/jsankey/work/my-app/build.gen

BUILD SUCCESSFUL
Total time: 0 seconds
jsankey@caligula:~/work/my-app$ cd test
jsankey@caligula:~/work/my-app/test$ ant clean run-tests
... clipped several lines of output ...
run-tests:
     [echo] Running tests ...
     [exec] 
     [exec] com.zutubi.android.myapp.test.MyAppActivityTest:.
     [exec] Test results for InstrumentationTestRunner=.
     [exec] Time: 0.147
     [exec] 
     [exec] OK (1 test)
     [exec] 
     [exec] 

BUILD SUCCESSFUL
Total time: 9 seconds

Then switch back to Eclipse, try editing and saving the activity and test cases and ensure everything is happy.

Checking It In

Finally, you can check the project into your version control system. I won’t go into the tool-specific details, just make sure you check in the correct files. You should exclude:

  • The bin/, build/, and gen/ directories: as these all contain build output.
  • The files local.properties and test/local.properties: which are intended to contain properties specific to your machine (e.g. the location of the Android SDK).

Make sure you don’t forget to check in the hidden Eclipse files .classpath, .project and .settings. By structuring the projects so they live under a single top-level folder, it should be easy to add them to the version control server of your choice.

Wrap Up

That covers the basics of setting up an Android project, with tests, for both development and automated builds. Although some tweaking is required, this setup is still built upon the tooling provided by the Android SDK. I hope that this will mean it is easy to take advantage of new capabilities when new SDK versions are released (which happens pretty frequently at the moment!).


1 For reasons unknown to me, when my projects were first created they had build errors. A clean rebuild magically fixed the problem.

Liked this post? Share it!

18 Responses to “Setting Up An Android Project Build”

  1. May 31st, 2010 at 5:48 pm

    Setting up Android SDK on Ubuntu 10.04 « Dev Blog says:

    […] * Once this is all installed, go ahead and load up eclipse and start a new android project. http://www.alittlemadness.com/2010/05/31/setting-up-an-android-project-build/ […]

  2. June 1st, 2010 at 3:31 pm

    Blog bookmarks 06/01/2010 « My Diigo bookmarks says:

    […] a little madness » Blog Archive » Setting Up An Android Project Build […]

  3. June 12th, 2010 at 6:00 am

    Blogging Round the World | Droid24 says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  4. June 12th, 2010 at 6:02 am

    Blogging Round the World | Android Unlocked says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  5. June 12th, 2010 at 7:10 am

    Planet Android » Blog Archive » Blogging Round the World says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  6. June 12th, 2010 at 12:49 pm

    Blogging Round the World | Android Application [dot] us says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  7. June 12th, 2010 at 8:47 pm

    Blogging Round the World | Android Phone Blog says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  8. June 12th, 2010 at 11:04 pm

    Blogging Round the World | Android Mobile Device says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  9. June 13th, 2010 at 10:11 am

    Blogging Round the World « top-android ???? says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  10. July 1st, 2010 at 8:15 am

    k5rud says:

    Mind helping out a somewhat new Eclipse / Jave / Android user with a question?

    When putting the Project directory under version control should the Eclipse .metadata directory be VC’d?

    One of my concerns is switching between my desktop and laptop machines for development. I don’t want files VC’d that will confuse the setup between the systems.

  11. July 1st, 2010 at 3:01 pm

    Jason says:

    Hi k5rud,

    No, you don’t want to put the .metadata directory under version control. It contains a bunch of state information for your Eclipse workspace, which is changing all the time.

    Just check in .classpath and .project, and when setting up the project on the new machine use File > Import … > General > Existing Project Into Workspace.

  12. July 1st, 2010 at 8:13 pm

    Android Solutions » Blogging Round the World says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  13. July 9th, 2010 at 5:07 pm

    Blogging Round the World | Mobile Compatible says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  14. August 6th, 2010 at 12:44 am

    Blogging Round the World | Android Based Phones says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  15. August 13th, 2010 at 7:55 am

    Blogging Round the World | Android Türkiye says:

    […] and Jason Sankey from Sydney run the Android-dense a little madness, and lay the rules out in Setting Up An Android Project Build. Lots of steps; but very handy for a command-line guy like […]

  16. February 19th, 2011 at 2:36 pm

    Rebecca says:

    Thanks for the tips! I was starting a project with someone and they had started it in Eclipse (ew) but I needed to build via command line. I’m glad all I needed was ‘android update project’!

  17. March 28th, 2011 at 8:13 am

    James Wald says:

    Thanks so much for this guide. While I had a bunch of hiccups along the way, I eventually got through it successfully. As far as your footnote:

    “1 For reasons unknown to me, when my projects were first created they had build errors. A clean rebuild magically fixed the problem.”

    This is caused by the ADT eclipse plugin not generating the gen source directory or R.java when they are missing or out of date. Sometimes a clean will cause ADT to kick in on the next build, but more often than not it won’t. Doing a clean then restarting eclipse is the best way to get the build to work again. I hope Google addresses this in an upcoming version of the ADT plugin.

    And that ant bug is still a bug in the version of ant that I have, thanks for providing the link to that bug report and workaround!

    One more note… you mention to include .settings in source control, unfortunately my .settings is an empty directory and I use Mercurial which only tracks files. I’ve been using MakeEmptyDirs to add placeholders inside empty directories so I can retain directory structures in my repository. After following this guide I had to run the tool again to pick up 3 new empty directories: .settings, libs, and test/libs

    Thanks again.

  18. September 19th, 2011 at 9:11 am

    Blah McBlah says:

    Google’s docs [1] explicitly encourage you to nest the test project into the main project, but AFAICS that’s not even officially supported by eclipse [2][3]. And EGit advises you not to use an eclipse project as the root of the git repository. So personally, right now I’m trying a setup like.

    blah/
    blah/.git
    blah/Blah/
    blah/Blah/AndroidManifest.xml
    … etc.
    blah/BlahTest/
    blah/BlahTest/AndroidManifest.xml
    … etc.

    [1] http://developer.android.com/guide/developing/testing/testing_eclipse.html

    [2] http://wiki.eclipse.org
    /Top_Ten_Architectural_Problems_in_all_of_Eclipse

    [3] https://bugs.eclipse.org/bugs/show_bug.cgi?id=35973

Leave a Reply