Tallan's Technology Blog

Tallan's Top Technologists Share Their Thoughts on Today's Technology Challenges

Build your Android project in one step with Maven

Cris Kim

Requirements

I will assume the following has been installed and configured.

  • Android SDK (r07 or later)
  • Maven 3 (version 3.0.3)
    1. Set environment variable ANDROID_HOME to point to the root directory of the Android SDK.
    2. Add ANDROID_HOME/tools to your PATH environment variable.
  • An Android project to build

Introduction

Building an Android project consists of 3 steps. The code is compiled to create an executable apk file, then the apk is signed and finally zipaligned to optimize disk space usage on the mobile device.

Executing these steps manually is prone to human error and can lead to bad builds. This can happen due to forgetting to sign the package, missing dependencies, etc. It is also time consuming especially if you have fast iteration cycles and/or multiple build configurations for different version of the Android OS. Using Maven and android-maven-plugin we can create a one step process to manage dependencies, build, sign and zipalign your Android project.

In this post I will walk you through the setup we have for TASS Mobile, our internal Android client for our time tracking application.

Breakdown of pom.xml

Basic information

The pom.xml file is the configuration file that tells Maven how to build the Android project. The first section of the configuration file includes basic information about the project such as name, groupId and version number. This is what it looks like for our TASS mobile app.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.tallan.tass</groupId>
  <artifactId>android</artifactId>
  <version>0.35-SNAPSHOT</version>
  <packaging>apk</packaging>
  <name>TASS Android</name>

Dependencies

This is where Maven really facilitates the build process. The TASS Mobile app for Android uses the guice and roboguice libraries for dependency injection. Fortunately guice and roboguice are available in the Maven central repository so all we need to do is include them under the dependency section along with the Android library. Make sure the Android version matches your target Android version.

  <dependencies>
    <dependency>
      <groupId>com.google.android</groupId>
      <artifactId>android</artifactId>
      <version>2.1.2</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.google.inject</groupId>
      <artifactId>guice</artifactId>
      <version>2.0-no_aop</version>
    </dependency>
    <dependency>
      <groupId>org.roboguice</groupId>
      <artifactId>roboguice</artifactId>
      <version>1.1</version>
    </dependency>
  </dependencies>

Build Steps

The standard maven-compiler-plugin in conjunction with maven-android-plugin will create the application apk file, it will also zipalign it after signing the apk which we cover in the next step. Make sure the platform variable is set to the target device Android OS version.

  <build>
    <finalName>${project.groupId}.${project.artifactId}-${project.version}</finalName>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3</version>
      </plugin>
      <plugin>
        <groupId>com.jayway.maven.plugins.android.generation2</groupId>
        <artifactId>maven-android-plugin</artifactId>
        <version>2.8.4</version>
        <configuration>
          <sdk>
            <platform>7</platform>
          </sdk>
          <emulator>
            <avd>16</avd>
          </emulator>
          <sign>
            <debug>false</debug>
          </sign>
          <zipalign>
            <verbose>true</verbose>
            <skip>false</skip>
            <inputApk>${project.build.directory}/${project.build.finalName}.apk</inputApk>
            <outputApk>${project.build.directory}/${project.build.finalName}-aligned.apk</outputApk>
          </zipalign>
          <undeployBeforeDeploy>true</undeployBeforeDeploy>
        </configuration>
        <executions>
          <execution>
            <id>zipalign</id>
            <phase>verify</phase>
            <goals>
              <goal>zipalign</goal>
            </goals>
          </execution>
        </executions>
        <extensions>true</extensions>
      </plugin>

In this section we configure maven-jarsigner-plugin to sign the apk file. Set the keystore, storepass, keypass and alias parameters with you own.

      <plugin>
        <artifactId>maven-jarsigner-plugin</artifactId>
        <version>1.2</version>
        <executions>
          <execution>
            <id>signing</id>
            <goals>
              <goal>sign</goal>
            </goals>
            <phase>package</phase>
            <inherited>true</inherited>
            <configuration>
              <archiveDirectory></archiveDirectory>
              <includes>
                <include>${project.build.directory}/target/*.apk</include>
              </includes>
              <keystore>c:/certs/tallan.keystore</keystore>
              <storepass>*****</storepass>
              <keypass>******</keypass>
              <alias>tallan</alias>
            </configuration>
          </execution>
        </executions>
      </plugin>

This step consolidates the application version in the pom.xml file with application version in the AndroidManifest.xml file. This will come handy when you setup a fully automated release management process.

      <plugin>
        <groupId>org.codehaus.groovy.maven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <phase>generate-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <source>
                try {
                def manifestFile = new File("AndroidManifest.xml")
                def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "ns")
                def parser = new groovy.util.XmlParser(false, true)
                def rootNode = parser.parse(manifestFile)
                def attributes = rootNode.attributes()
                attributes[ns.versionName] = "${project.version}"
                def writer = new groovy.io.GroovyPrintWriter(manifestFile)
                writer.println('&lt;?xml version="1.0" encoding="UTF-8"?&gt;')
                def xmlWriter = new groovy.util.XmlNodePrinter(writer)
                xmlWriter.setPreserveWhitespace(false)
                xmlWriter.setNamespaceAware(true)
                xmlWriter.print(rootNode)
                } catch (FileNotFoundException e)
                {
                println('No AndroidManifest.xml file found. Skipping version update.')
                println('Probably not an Android project, but a library.')
                println('Skipping version update.')
                }
              </source>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Profiles

This is the default profile I’ve created for building, signing and ziapligning the project. There are other options available but this is all you need to create a usable build.

  <profiles>
    <profile>
      <id>release</id>
      <activation>
        <activeByDefault>true</activeByDefault>
        <property>
          <name>performRelease</name>
          <value>true</value>
        </property>
      </activation>
    </profile>
  </profiles>
</project>

Once you have configured your project all you need to do is type the following command and Maven will build a binary ready to run on your Android device. Look for the apk file under the target/ folder in your project.

mvn clean install -Prelease

or simply

mvn clean install

Files

pom.xml

No comments

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>