Android, Maven and Hudson. Pardon me, Jenkins. - codecentric AG Blog

:

Android platform is based on Java but is somehow different. It compiles into Dalvik rather than into Java byte code and runs in emulator which is enough to make some of your standard Java tools fail and become unusable. There was one specific problem I was interested in. I must say, there is number of articles describing how to build Android applications using Maven and CI environment but none of those was helpful enough for me. I had to mash up things I’ve learned from all of those in order to make it work. So, the goal of this article is present a setup of simple Android-Maven project and to show how to configure it to run nicely on Hudson. Pardon me, Jenkins. Hopefully, this article will be enough for you to do the same.

First of all you will have to have Java installed (naturally), Eclipse (in my case it was Helios), Maven and Android SDK. Along with that, you will have to configure your Eclipse (Android SDK location, Java JDK, Maven) but I’ll skip that and act as it is all already configured properly.

What we need as additional tools? Some Eclipse plug-ins, of course. We need M2Eclipse plug-in to ease up work with Maven projects, Android Development Toolkit to ease up work with Android projects and bridge between those two to ease up work with Maven-Android projects: Maven Integration for Android Development Tools plug-in.

When those plug-ins are installed, we can create our first AVD (Android Virtual Device) – it will actually be an instance of emulator with specific options and features which we will use for testing the application. It can be created using Android SDK and AVD Manager by pressing the small Android button marked on the pic bellow. Once the AVD Manager is started, new window is opened and user can create virtual device (by pressing the button “New”) and specify its features: camera support, GPS support, existence of SD card, etc… Information regarding created virtual devices is placed in ${USER_HOME}/.android/avd. Each AVD will have its own directory and its own ini file. You will distinguish it easily by name you have given to the virtual device.

At the moment we have IDE set up, emulator is ready, but we don’t have any application to run. So, it is the right time to create new project. To state it once more, we want it to be Maven-Android project.

These are the steps to create new Android project in Eclipse:
File -> New -> Other -> Android -> Android project -> new dialog opens
– give project a name
– choose location for your new project
– choose API level (Android platform you want your application to runs on)
– give you application a name
– choose package name (where your sources will be)
– choose main activity name (optional)
– specify minimal API level your application will require
– click next -> new dialog opens

When prompted to create new test project, please skip that action, as we will come to that later after a bit of configuration of actual application project.

So, we have created new Android project and its structure is similar to this one,example project structure
but we want to make it Maven project also. For that reason we have to create pom file with all dependencies and enable Maven dependency management in Eclipse.

When it is enabled, Maven took over and slightly changed the structure of our project. For example, from now on we don’t need bin directory (which was default output for Android project) – directory named target is place where class files will go. This specific fragment from our pom file

<build>

<pluginManagement>

<plugins>

<plugin>

<inherited>true</inherited>

<groupId>com.jayway.maven.plugins.android.generation2</groupId>

<artifactId>maven-android-plugin</artifactId>

<version>2.8.3</version>

<configuration>

<deleteConflictingFiles>true</deleteConflictingFiles>

<undeployBeforeDeploy>true</undeployBeforeDeploy>

<sdk>

<platform>8</platform>

</sdk>

<device>emulator</device>

<emulator>

<avd>Device1</avd>

<wait>60000</wait>

</emulator>

</configuration>

<extensions>true</extensions>

<executions>

<execution>

<id>alignApk</id>

<phase>package</phase>

<goals>

<goal>zipalign</goal>

</goals>

</execution>

</executions>

</plugin>

</plugins>

</pluginManagement>

<plugins>

<plugin>

<groupId>com.jayway.maven.plugins.android.generation2</groupId>

<artifactId>maven-android-plugin</artifactId>

</plugin>

</plugins>

</build>

tells Android which emulator instance will start when we start the app. The name of the specified AVD must be the same as the name of the AVD we created with AVD manager. It means that, at this point, we have the simplest application that can be run on emulator by choosing Run As -> Android Application from its context menu.

With this all done and set, it’s time to create test project. What is test project? Test project is separate project containing only tests and resources needed for tests. “But, shouldn’t unit tests be contained by the same project where application is?”, one could ask. Yes, that’s absolutely right. These are not unit tests. These are acceptance tests. Unit tests should be in application project, in test directory.

So, here are the steps to create test project:
right-click on application project -> New -> Other -> Android Test Project -> new dialog opens
– give test project a name
– choose location for your test project
– choose project which you want to test
– choose application name
– other values are set automatically
– click finish

The result is new Android project, as it was when we created our application project, so create pom file and enable maven dependency management. This is the right moment to point out some important things regarding test project configuration. This is how pom build fragment should look like:

<build>

<plugins>

<plugin>

<groupId>com.jayway.maven.plugins.android.generation2</groupId>

<artifactId>maven-android-plugin</artifactId>

<extensions>true</extensions>

<configuration>

<enableIntegrationTest>true</enableIntegrationTest>

<autoStartEmulator>true</autoStartEmulator>

<deleteConflictingFiles>true</deleteConflictingFiles>

<undeployBeforeDeploy>true</undeployBeforeDeploy>

<sdk>

<platform>8</platform>

</sdk>

<device>emulator</device>

<emulator>

<avd>Device1</avd>

<wait>60000</wait>

</emulator>

</configuration>

</plugin>

</plugins>

</build>

This way we told maven to run integration tests and to start emulator (AVD with name Device1) when it’s time to do so. Furthermore, we told it to run emulator with API level 8 (Android 2.2) and to wait one minute before running tests to give time to emulator to fire up. It is very important to say which are dependencies that we need to test a project. Naturally, we need Android and Android test libraries. Also, Robotium can ease the job very much, so I added that one too. At the end, we need dependency to the project we are testing, both jar and apk. Jar dependency is needed to provide compiler with java classes and apk is needed to provide application to run tests against it on emulator. So, dependency pom fragment should look similar to what follows:

<dependencies>

<dependency>

<groupId>de.codecentric</groupId>

<artifactId>example</artifactId>

<version>${appproject.version}</version>

<type>apk</type>

</dependency>

<dependency>

<groupId>de.codecentric</groupId>

<artifactId>example</artifactId>

<version>${appproject.version}</version>

<type>jar</type>

</dependency>

<dependency>

<groupId>com.google.android</groupId>

<artifactId>android</artifactId>

<version>${android.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.google.android</groupId>

<artifactId>android-test</artifactId>

<version>${android.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.jayway.android.robotium</groupId>

<artifactId>robotium-solo</artifactId>

<version>${robotium.version}</version>

</dependency>

</dependencies>

When have all of this set up, it’s time to configure Hudson, i.e. Jenkins. What we need is Android Emulator Plugin (http://wiki.jenkins-ci.org/display/JENKINS/Android+Emulator+Plugin). This is plugin that will let you automatically generate and run an Android emulator for the duration of a build, with the emulator logs being captured as artifacts. Since this post is having tendency to become really big, I will not provide details about its configuration, but will tell you that you can find all that you need if you follow link I provided.

After you configured Android plugin to act as you want it to and wired up Hudson, pardon me, Jenkins, with you SCM tools, your CI-Android environment is ready. And this is exactly what we wanted to have. In addition, if you want to run more than one Android emulator instances in parralel, you might want to take a look at this plugin: http://wiki.jenkins-ci.org/display/JENKINS/Xvnc+Plugin.

I hope I helped a bit.