Sunday, January 17, 2010

Android Continuos Integration: Build with maven

Android Continuous Integration: Build with maven

This document can be read in Google Docs (, cut and paste link if you have problems accessing it.

If you have problems seeing the images, like the icon in this box don't blame me, it seems to be an issue when you publish to Blogspot from Google Docs.


"Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible."

We have written some tests for our project and now we would like to take continuous integration into account, mainly if we are working in an enterprise development environment and our team has several developers.

We all are very much accustom to use Eclipse and Android ADT as our main developer environment, so it's logical that even though we are increasing our team size we don't want to left behind that experience and start using a different tool from scratch. At the same time, it's pretty clear that using maven as a build tool for the project we obtain a great level of simplification, mainly if we use hudson, cruise control or similar continuous integration tools.

That's why the approach presented here is to let both models co-exist.

    project structure

    We are also considering here that a VCS is used and a parent project containing both the main and test project is under this VCS control.

    The structure of our project P1 will be

    the P1 project including AP1 application's main project and its tests in AP1Test.

    To create these projects you should follow this sequence:

    1. Create a Project (File -> New... -> Project), P1 in this case
    2. Add a pom.xml file (File -> New... -> Other -> Maven -> Maven POM file). We will review its content later
    3. Create an Android Project (New... -> Android Project), AP1, using P1 folder instead of the default location, but DON'T create the test project yet or it will fail (ADT 0.9.5)
    4. Add a pom.xml file to AP1 (File -> New... -> Other -> Maven -> Maven POM file). We will review its content later
    5. Selecting AP1 project, create the corresponding test project AP1Test (Android Tools -> New Test Project) using again P1 as the location
    6. Add a pom.xml file to AP1 (File -> New... -> Other -> Maven -> Maven POM file). We will review its content later
    7. You can now import the whole project structure to your VCS

    pom files

    You need to define some things inside your pom files in order to get the Android projects correctly built.

    P1's pom.xml

    We are using maven-android-plugin here, visit its site for further details.

     1 <project xmlns="" xmlns:xsi="" xsi:schemaLocation="">

     2   <modelVersion>4.0.0</modelVersion>

     3   <groupId>P1</groupId>

     4   <artifactId>P1</artifactId>

     5   <packaging>pom</packaging>

     6   <version>0.0.1-SNAPSHOT</version>


     8    <build>

     9         <sourceDirectory>src</sourceDirectory>

    10         <plugins>

    11             <plugin>

    12                 <groupId>org.apache.maven.plugins</groupId>

    13                 <artifactId>maven-compiler-plugin</artifactId>

    14                 <version>2.1</version>

    15                 <configuration>

    16                     <source>1.6</source>

    17                     <target>1.6</target>

    18                 </configuration>

    19             </plugin>

    20             <!--

    21                maven-android-plugin doesn't delete files from bin,

    22                only from target, we are deleting them here

    23             -->

    24             <plugin>

    25                <groupId>org.apache.maven.plugins</groupId>

    26                <artifactId>maven-clean-plugin</artifactId>

    27                <version>2.2</version>

    28                <configuration>

    29                   <filesets>

    30                      <fileset>

    31                         <directory>bin</directory>

    32                         <includes>

    33                            <include>**/*</include>

    34                         </includes>

    35                      </fileset>

    36                      <fileset>

    37                         <directory>gen</directory>

    38                         <includes>

    39                            <include>**/*</include>

    40                         </includes>

    41                      </fileset>

    42                   </filesets>

    43                </configuration>

    44             </plugin>

    45             <plugin>

    46                 <groupId></groupId>

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

    48                 <configuration>

    49                     <sdk>

    50                         <!--



    51                         <path>/opt/android-sdk/</path>

    52                         <platform>2.1</platform>

    53                     </sdk>

    54                     <deleteConflictingFiles>true</deleteConflictingFiles>

    55                 </configuration>

    56                 <extensions>true</extensions>

    57             </plugin>

    58         </plugins>

    59     </build>

    60    <modules>

    61       <module>AP1</module>

    62       <module>AP1Test</module>

    63    </modules>

    64    <dependencies>

    65       <dependency>

    66          <groupId>android</groupId>

    67          <artifactId>android</artifactId>

    68          <version>2.1</version>

    69          <type>jar</type>

    70          <scope>provided</scope>

    71       </dependency>

    72    </dependencies>


    74     <dependencyManagement>

    75         <dependencies>

    76             <dependency>

    77                 <groupId>android</groupId>

    78                 <artifactId>android</artifactId>

    79                 <version>2.1</version>

    80                 <scope>provided</scope>

    81             </dependency>

    82         </dependencies>

    83     </dependencyManagement>

    84 </project>

    Basically we
    1. define our source directory as src to be compatible with the Eclipse Android project structure
    2. configure the maven-compiler-plugin according to our needs
    3. clean Eclipse Android project structure too in our clean goal
    4. configure maven-android-plugin defining the location of the Android SDK. This can be defined here or read from the environment
    5. define our modules, in this case the main project AP1 and its tests AP1Test
    6. define the dependencies, android 2.1 in this case

    AP1's pom.xml

     1 <project xmlns="" xmlns:xsi="" xsi:schemaLocation="">

     2   <modelVersion>4.0.0</modelVersion>

     3   <groupId>AP1</groupId>

     4   <artifactId>AP1</artifactId>

     5   <packaging>apk</packaging>

     6   <version>0.0.1-SNAPSHOT</version>

     7   <parent>

     8    <artifactId>P1</artifactId>

     9    <groupId>P1</groupId>

    10    <version>0.0.1-SNAPSHOT</version>

    11   </parent>

    12 </project>

    AP1Test's pom.xml

     1 <project xmlns="" xmlns:xsi="" xsi:schemaLocation="">

     2   <modelVersion>4.0.0</modelVersion>

     3   <groupId>AP1Test</groupId>

     4   <artifactId>AP1Test</artifactId>

     5   <packaging>apk</packaging>

     6   <version>0.0.1-SNAPSHOT</version>

     7   <parent>

     8    <artifactId>P1</artifactId>

     9    <groupId>P1</groupId>

    10    <version>0.0.1-SNAPSHOT</version>

    11   </parent>

    12   <dependencies>

    13    <dependency>

    14       <groupId>AP1</groupId>

    15       <artifactId>AP1</artifactId>

    16       <version>0.0.1-SANPSHOT</version>

    17    </dependency>

    18    <dependency>

    19       <groupId>AP1</groupId>

    20       <artifactId>AP1</artifactId>

    21       <version>0.0.1-SNAPSHOT</version>

    22       <type>apk</type>

    23    </dependency>

    24   </dependencies>

    25 </project>

    populating your local repository

    For maven to find android dependencies you must populate your local repository. To ease the task you can use android-mvn-install script which do all the hard work for you.
    Just run

    $ wget -qO - | bash -s -- --sdk-dir=/opt/android

    or download from its page and run it locally.
    There's an alternative for this step, maven-android-sdk-deployer, however I prefer the simplicity and flexibility of the android-mvn-install script.

    building the project

    Now we have several alternatives to build our project:
    • using Eclipse as usual for other Android projects using ADT plugin (i.e.: AP1 -> Run As -> Android Application)
    • using Maven from Eclipse (i.e.: P1 -> Run As -> Maven build)
    • using Maven from the command line (i.e.: mvn install)
    • using a continuous integration tool

    using hudson

    Having followed all the steps mentioned before we will now be able to create a job in hudson to build our project using maven


    There are still some rough edges and some things we haven't mentioned yet like running headless android emulators to be able to run the tests on the server. We will be covering these issues in future posts but I think that we have enough already to start applying continuous integration for our android projects.

    Comments are gladly welcome.

    Copyright © 2010 Diego Torres Milano. All rights reserved.

    Post a Comment