Tobias Knell
13.09.2013Building Android projects with Maven – Part 1: Setup
Building and managing Android projects with maven is not as easy as it could be. So in this blog, I’ll show you how we managed to get it work nicely.
In this example, we’ll create a parent project with an app module and a separate instrumentation tests module.
Project setup
The quickest approach to create a new Android project with maven is using a maven archetype from aquinet (http://mvnrepository.com/artifact/de.akquinet.android.archetypes).
For this project, we’ll use the android-release archetype, as it creates a skeleton for exactly our case, as we also want to release the app with maven.
Hint: be sure to use the latest version of the archetype
mvn archetype:generate -DarchetypeArtifactId=android-release -DarchetypeGroupId=de.akquinet.android.archetypes -DarchetypeVersion=1.0.9 -DgroupId=com.foo.bar -DartifactId=my-android-project -Dpackage=com.foo.bar.android
With this, a parent project named after the artifactId gets created in your current directory. Inside, you’ll find two modules, one for the app and one for the instrumentation tests, and the pom.xml of the parent is also already pre-configured with both of them as modules. In the pom, you’ll find several plugins already configured for you, on top of all the android-maven-plugin
Now check the pom for the android-maven-plugin version and update it to the latest version (3.6.1 at the moment I wrote this blog). It should be at least 3.6.0 – if not, the build will fail, because the aapt tool can’t be found as it moved in a previous android release and the plugin only considers this since version 3.6.0.
To test the setup, simply go into the parent project and run
mvn clean install
Now everything should be compiled and the instrumentation tests should run on any emulator or device that is connected.
If you get an error stating “Platform/API level 16 not available”, install it via the SDK Manager, or replace the sdk version in the pom to an available one.
In the android-maven-plugin config:
<sdk>
<platform>16</platform>
</sdk>
Note: the archetypes from aquinet also include their androlog logging framework which is a wrapper around the Android logging that adds the functionality of disabling the logging for releases and provides log4j-like configuration. You could remove it from the poms, or you could give it a try, which I would recommend you to 🙂
Setting up Android Studio to work with maven
To conveniently work on a maven project with Android studio, we have to set it to automatically import Maven projects, so that it notices changes to the pom.xml and updates it’s dependencies.
File -> Settings -> Maven -> Importing -> Import Maven projects automatically
Import the project:
- File -> Import project
- Select your parent project
- Import from external model -> Select Maven
- Check “Import Maven projects automatically” -> Next
- Select the Android platform -> Next
- Finish
configure Android Studio to also build using Maven:
- Select the project
- Run -> Edit Configurations
- “+” Android Application
- Module: select Android App
- Launch default Activity
- Select default target device
- Before Launch: remove “Make”
- Before Launch: add Maven “clean install”
- OK
Now if you run the project in Android studio, Maven will be used.
Running Android Lint
It’s recommended to run Android Lint to check warnings and errors. To run it with the android-maven-plugin, simply insert this config to the android-maven-plugin int the pom (and edit the sources path accordingly to your project):
<lint>
<skip>false</skip>
<sources>${project.basedir}/my-android-project/src/main/java/</sources>
<enablehtml>true</enablehtml>
<enablexml>false</enablexml>
</lint>
If you want to execute android lint on the build, add android:lint to the maven commands (e.g. “mvn clean install android:lint”)
Don’t forget to edit the Run config you previously created to include “android:lint”!
The results will be written to /target/lint-results/lint-results-html/. (We disabled the XML output and enabled HTML, because it just has a better readability and you have a way better overview on the HTML pages)
Create a separate Instrumentation Test Profile
We don’t want to install the app and run the Instrumentation Tests on every build, because it just takes so long. So we’ll execute the tests only in a separate maven profile.
First, we’ll disable the instrumentation tests for all cases by inserting a configuration for the android-maven-plugin in the parent pom:
<configuration>
<test>
<skip>true</skip>
</test>
...
</configuration>
In the parent pom, add the new profile “IT”:
<profile>
<id>IT</id>
</profile>
And in the pom of the IT module, we also add the IT profile and enable the tests for it again:
<profile>
<id>IT</id>
<build>
<plugins>
<plugin>
<groupid>com.jayway.maven.plugins.android.generation2</groupid>
<artifactid>android-maven-plugin</artifactid>
<inherited>true</inherited>
<configuration>
<test>
<skip>false</skip>
</test>
</configuration>
</plugin>
</plugins>
</build>
</profile>
To test it, run
mvn clean install
The Instrumentation Tests should not run. And then
mvn clean install -PIT
Now the tests should run.
Dependencies on android libraries
The dependencies on the android libraries are some kind of problem, because not all of them are published in maven central (e.g. only up to Android 4.1.1.4 right now, and only the support-v4 library, not the -v7 one…)
To compensate this, there is the maven-android-sdk-deployer project that lets you deploy your local sdk components into a maven repository of your choice (defaults to your local one).
For the tutorial on how to use it, please head over to their github page, everything is explained nicely detailed there.
Just some small pointers for this this setup: if you have a dependency on a apklib (except from the android framework itself), define the dependency in the parent project to define the version:
<dependency>
<groupid>android.support</groupid>
<artifactid>compatibility-v4</artifactid>
<version>18</version>
</dependency>
In the app,
<dependency>
<groupid>android.support</groupid>
<artifactid>compatibility-v4</artifactid>
</dependency>
And in the IT module, set it as provided!
<dependency>
<groupid>android.support</groupid>
<artifactid>compatibility-v4</artifactid>
<scope>provided</scope>
</dependency>
If you want to use newer versions than the preconfigured 4.1.1.4, you have to deploy them yourself and also use another group id for android, simply “android” instead of “com.google.android”. For the exact versions, deploy them with the maven-android-deployer and look into your repository, or simply look at the readme at the github page of the deployer.
Here’s an example config of the dependencies deployed with the maven-android-deployer:
<properties>
<platform.version>4.2.2_r2</platform.version>
<android.platform>17</android.platform>
</properties>
<dependencymanagement>
<dependencies>
<dependency>
<groupid>android</groupid>
<artifactid>android</artifactid>
<version>${platform.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupid>android.test.uiautomator</groupid>
<artifactid>uiautomator</artifactid>
<version>${platform.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencymanagement>
Don’t forget to update the modules dependencies accordingly!
As you can probably see, we also replaced the sdk platform version config with a parameter, in the android maven plugin config:
<sdk>
<platform>${android.platform}</platform>
</sdk>
With this you should be able to develop Android (more or less comfortable) using maven and Android studio.
In the next blog, I’ll show you how to configure the plugins to build releases of Android apps!
I’ll also post the sources for the project at the end of the next blogpost, so you can check against it, if you get some errors.