My little project is made of 3 modules: a parent Maven project – for keeping things together, an Android project for the application logic and ui and an Android project for running integration tests with Robotium. In some cases (e.g. you want to have a common base code and then 2 different ui implementations for handsets and tablets) it is useful to have an Android Library Project which then the 2 other can depend on. The android-maven-plugin packages the library project as .apklib and you can find the tutorial here.
To download the dependencies needed by your project you have at least 3 choices:
1. Let Maven automatically find and download them from Maven Repository – might not all be available
2. Use the maven-android-sdk-deployer which installs the android jars from your SDK into your local repository (~/.m2/repository)
3. Setup your own enterprise repository with Sonatype Nexus, where you can add whatever jar you might need and can’t find on other sources. Then all you need to do is to let Maven know where to look:
<repositories> <repository> <id>Nexus</id> <url>http://myip:myport/nexus/content/repositories/releases</url> </repository> </repositories>
The parent .pom file contains a description of what dependencies will be managed top-level to be used by children projects. This doesn’t actually download them in your local repository, but lets you use a simpler way of including the dependencies later on. For e.g. you can skip specifying the <version/> or even the <groupId/> on some cases.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>${android.version}</version>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android-test</artifactId>
<version>${android.version}</version>
</dependency>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android-support</artifactId>
<version>${android.support.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
The dependencies that I’ll need in more than one module are the android jars (for instrumentation tests as well), junit and the android compatibility (support) library.
The same you can do for specifying how certain plugins that are used in the children modules behave inside <pluginManagement/>. For e.g. here’s the android-maven-plugin:
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>${android.maven.plugin.version}</version>
and below is what I’ve configured it to do (with comments):
<configuration>
<!-- Give the path to your Android SDK and the Android version you're using -->
<sdk>
<path>${env.ANDROID_HOME}</path>
<platform>${android.api.level}</platform>
</sdk>
<!-- For the testing phase, this plugin will need to run an emulator called
'Default', that needs to be available in $HOME/.android/avd/ folder as Default.avd -->
<emulator>
<avd>Default</avd>
<wait>60000</wait>
<options>-no-boot-anim -wipe-data -no-window</options>
</emulator>
<zipalign>
<verbose>true</verbose>
</zipalign>
<!-- ProGuard is a free Java class file shrinker, optimizer, obfuscator,
and preverifier. It detects and removes unused classes, fields, methods,
and attributes. It optimizes bytecode and removes unused instructions. It
renames the remaining classes, fields, and methods using short meaningless
names.This plugin will read the Proguard configurations inside specified
file. -->
<proguard>
<config>proguard.cfg</config>
</proguard>
<!-- Remove the existing .apk from the device/emulator before installing
the newly built .apk file. -->
<undeployBeforeDeploy>true</undeployBeforeDeploy>
</configuration>
I opted for not showing the emulator window when running the automated instrumentation tests because I had a strange problem: the emulator starts with the screen lock and the tests are not running properly. If you really need to see the emulator, remove the -no-window option. If you still have the locking problem, here’s a script that sends some key events to the emulator via telnet to simulate unlocking the screen. You can run that script with Exec Maven Plugin like below (put this inside your test project’s pom):
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>unlock_emulator.sh</executable>
<workingDirectory>${project.parent.basedir}</workingDirectory>
</configuration>
</plugin>
</plugins>
</build>
The unlocking bash script (I’m not an expert in scripting, but I assume it can be done better in Python or whatever)
host=localhost
port=5554
cmd="event send EV_KEY:KEY_MENU:1 EV_KEY:KEY_MENU:0"
( echo open ${host} ${port}
sleep 1
echo -e "\r"
sleep 1
echo ${cmd}
sleep 1
echo -e "\r"
sleep 1
echo exit ) | telnet
sleep 10
To be continued…