Category: Automation

Automate SLAMD extension testing using Maven

I wanted to automate start of my SLAMD server for faster development time when porting on façades to the underlying SLAMD system. SLAMD ships with a Tomcat 6 server so the obvious way to do this is to use the Cargo plugin for Maven.

Below is the configuration that automatically pushes my classes to the server and then starts the server. They are configured in a profile since I don’t want this to happen on all builds.

...


      debug
        


              org.codehaus.mojo
              exec-maven-plugin
              1.1.1
              
                
test
                
                  exec
                
                
                  rm
                  
                    -Rf
                    ${slamd.local.server.root}/webapps/slamd/WEB-INF/classes/com
                  
                  cp
                    
                      -Rf
                      ${project.build.outputDirectory}
                      ${slamd.local.server.root}/webapps/slamd/WEB-INF/
                     
                   
                 
               
             

               org.codehaus.cargo
               cargo-maven2-plugin
               
                 true
                 
                 tomcat6x
                 installed
                 ${slamd.local.server.root}
               
               
                 existing
                 ${slamd.local.server.root}
               
             
             
               
package
                 
                   start
                 
               
             
           
         
       
     
  
...

This will first remove any classes from the SLMD web app in the Tomcat container that lives under the package com. It will then copy all built classes to the SLAMD server. It will then launch Tomcat and wait for a ctrl-c to break execution. This will all happen in the package build phase.

This makes it fairly quick to deploy and test changes made to extensions of the SLAMD server.

How to modify the version code and version name in the AndroidManifest using GMaven

After having automated our android project and getting everything to work, up and running on hudson and so on, we realised that the Android manifest xml file did not get automatically updated with the correct version numbers.

My initial idea was to use normal Maven properties, we do that in other parts of the project, to populate the values. However this does not work since the versionCode attribute must have an integer value for Eclipse to work. This ment that I would need to change the actual values in the manifest.

I had read a couple of blog posts about a Maven plugin called GMaven that have intrigued me. The plugin makes it possible to embed a Groovy script into a pom file and execute it during the build. Since Groovy makes changing XML easy this was the perfect fit.

Below is a script, embedded into the pom directives needed, that will automate setting version in the AndroidManifest.xml. It is triggered using the profile manifest-version-update. When triggered it will set the versionName attribute to the maven project version. It will also increment the versionCode attribute with 1 (versionCode++). The script should be placed in the Android application pom (I.E if you use a hierarchical structure this does not go in the parent pom).

<profile>
<id>manifest-version-update</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
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()
def versionNumber = attributes[ns.versionCode]
versionNumber++
attributes[ns.versionCode] = versionNumber
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)
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

I have yet to figure out how I can automatically trigger this when running the Maven release plugins prepare step. It would be perfect if it can be triggered once for the release pom and once for the snapshot pom during the release:prepare phase so that both the release tag and the trunk of the project has the correct version numbers. But that will have to wait a while.

Adding the zipalign command to the Maven Android build

When creating an application that will be distributed to more then your self you want to do it the proper way. So far I have looked at how to automate the build, testing and both using Maven, as well as how to sign the apk. What is still outstanding is to run zipalign, a tool in the Android SDK to optimise the package.

To understand what the zipalign tool is you will find Androids documentation here.

It is a simple thing to add the command to the pom file. I am assuming that your project structure looks like the examples build in the previous posts.

In the pom for your application you need to add the following snippet:


sign
org.codehaus.mojo
exec-maven-plugin
1.1.1

zipalign

exec
package
${ANDROID_HOME}/tools/zipalign

-f
4
target/${project.build.finalName}.apk
target/${project.build.finalName}-zipped.apk

This will bind execution of zipalign to the package phase, just after the apk signing, when running install with the sign profile. It will overwrite previous zip aligned file without asking.

How to sign an Android application using Maven

One function that have not yet made it in to the Maven Android plugin is application signing (it is raised as an issue). It is however possible to achieve this using the maven jarsigner plugin with some simple configuration of the pom.

It is assumed that you are using the project structure presented in previous blog posts on maven android automation (1, 2, 3)

In your parent pom you add the following profile:


sign
org.apache.maven.plugins
maven-jarsigner-plugin
1.2

signing

sign
package true

target/*.apk

path/to/keystore
storepasword
keypassword
key-alias

com.jayway.maven.plugins.android.generation2
maven-android-plugin
true

false

Replace the following values in the above snippet:

  1. keystore the path to your key store.
  2. keypass the password for the key that will be used.
  3. storepass the password for the key store.
  4. alias the alias for the key to use.

To sign the apks, including the tests, use the following command:

mvn install -Psign

The configuration will bind the jarsigner plugin to the package phase of the execution when enabled with the -Psign switch in the build. Rather then storing the passwords in clear text in your pom you can pass them to maven as arguments when you execute the command. Go to the jarsigner plugins documentation page for information on how it works and how it can be configured.

Using Maven to automate build and test of Android in one command

The last post explored how to automate a Android test project that is associated with an Android application. It also introduces some unneeded complexity in how each project has to be built individually for the tests to run. This is easy to do away with by using Mavens built in project hierarchy.

To achieve this a new directory needs to be created. In the new directory the two android projects (the application and the test projects) should be placed. Ensure that the names of the directories matches that of the artifact name specified in the pom for each project.

Now a pom.xml needs to be created that holds information which is similar for both project and also reference the two projects. Mine look like this:


4.0.0
com.yourcompany
your-parent-project-artifact-id
pom
0.0.1
Your Android project parent

your-artifact-id
your-test-artifact-id


src


org.apache.maven.plugins
maven-compiler-plugin

1.6
1.6



com.jayway.maven.plugins.android.generation2
maven-android-plugin


${env.ANDROID_HOME}
1.6

true

true






android
android
1.6
provided




It is important to note what the names in the modules section are. They need to correspond with the directory names of the two modules, and the directory names should in turn match the artifact id’s of each of the modules.

Next we will need to change the pom files of the two modules, the application and test pom files. The following needs to change:

  • The build section can be removed. It will be inherited from here.
  • The child projects need to know it’s parent. This is done by adding the following to the top of each pom:
    
    com.yourcompany
    your-parent-project-artifact-id
    0.0.1
    
    
  • In the dependencyManagement section in the parent pom the version number and scope for the android jar file is specified. That makes this information is redundant in the child poms. So removing it will ensure clean build files.

Once this is done you can go to the directory where your parent project is and run the command:

mvn install

This will trigger the build and test of your Android project.

Having done this it is very simple to add your Android project to your favorite CI server. What you need to keep in mind is that in order for the tests to work you need to have either a connected device or a running emulator.