In this section, we will talk about some useful tools for our code.
In this section, we will create a profile to install the application automatically and run instrumentation tests at every build.
For convenience, we will refer to our profile as testProfile
and perform the following steps:
[…] <build> <sourceDirectory>src</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> </build> […]
[…] <properties> <skipTests.value>true</skipTests.value> </properties> […]
[…] <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> […]
Tests
in the previously created directory, src/test/com/androidmavenproject
:package com.androidmavenproject; import junit.framework.Assert; import org.junit.Test; public class Tests { @Test public void testEquals() { Assert.assertEquals("Hello World", "Hello World"); } }
maven-surefire-plugin
artifact ID to the build
tag and run the application. We can see the maven-surefire-plugin
artifact ID's following code:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.12.4</version> <configuration> <skipTests>${skipTests.value}</skipTests> </configuration> </plugin>
You should get a result like the following:
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ android-maven-project --- [INFO] Tests are skipped.
testProfile
profile in the POM file:[…] <profiles> <profile> <id>testProfile</id> <properties> <skipTests.value>false</skipTests.value> </properties> </profile> </profiles> […]
Note that the property to skip the test is set to false
.
-P
flag:$ mvn clean install -PtestProfile
We should get a result like the following:
T E S T S ------------------------------------------------------- Running com.androidmavenproject.Tests Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
To sign and zipalign the package, perform the following steps:
releaseProfile
that will serve to release the APK:[…]
<profile>
<id>releaseProfile</id>
<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>
</profile>
[…]
[…] <properties> <sign.keystore>pathtokeystorefile</sign.keystore> <sign.alias>aliasname</sign.alias> <sign.keypass>somepassword</sign.keypass> <sign.storepass>somotherpassword</sign.storepass> </properties> […]
sign.*
properties with your keystore
values. Finally, add the JAR-signing process into the build profile:<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jarsigner-plugin</artifactId> <executions> <execution> <id>signing</id> <goals> <goal>sign</goal> <goal>verify</goal> </goals> <phase>package</phase> <inherited>true</inherited> <configuration> <removeExistingSignatures>true </removeExistingSignatures> <archiveDirectory/> <includes> <include>${project.build.directory}/${project.artifactId}.apk</include> </includes> <keystore>${sign.keystore}</keystore> <alias>${sign.alias}</alias> <storepass>${sign.storepass}</storepass> <keypass>${sign.keypass}</keypass> <verbose>true</verbose> </configuration> </execution> </executions> </plugin> […]
[…] <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>maven-android-plugin</artifactId> <inherited>true</inherited> <configuration> <sign> <debug>false</debug> </sign> <zipalign> <verbose>true</verbose> <inputApk> ${project.build.directory}/${project.artifactId}.apk </inputApk> <outputApk> ${project.build.directory}/${project.artifactId}-signed-aligned.apk </outputApk> </zipalign> </configuration> <executions> <execution> <id>alignApk</id> <phase>package</phase> <goals> <goal>zipalign</goal> </goals> </execution> </executions> </plugin> […]
$ mvn clean install –PreleaseProfile
The output will be something like the following:
[INFO] --- maven-jarsigner-plugin:1.3.2:verify (signing) @ android-maven-project --- [INFO] 2 archive(s) processed [INFO] [INFO] --- android-maven-plugin:3.0.0-alpha-11:zipalign (alignApk) @ android-maven-project --- [INFO] Running command: …eclipseadt-bundle-windows-x86_64sdk oolszipalign.exe [INFO] with parameters: [-f, 4, …workspaceAndroidMavenProject argetandroid-maven-project-0.1.0.apk, …workspaceAndroidMavenProject argetandroid-maven-project-0.1.0-aligned.apk] [INFO] Attach …workspaceAndroidMavenProject argetandroid-maven-project-0.1.0-aligned.apk to the project
As you can see, the zipalign procedure will take the APK file as input and produce a new output called ${project.artifactId}-signed-aligned.apk
.
There are several tools to identify potential bugs in our code. In this section, we will see the dedicated plugin for Android, and this tool is called lint.
Android lint is a new tool introduced in ADT 16 (and Tools 16). Lint can check missing translations, unused resources, and other common mistakes in Android programming.
Now, let's see a simple example to generate an HTML report using the errors of our project. We need to change the Android plugin by adding a few simple lines:
[…] <configuration> <sdk> <path>${env.ANDROID_HOME}</path> <platform>19</platform> </sdk> <deleteConflictingFiles>true</deleteConflictingFiles> <undeployBeforeDeploy>true</undeployBeforeDeploy> <lint> <skip>false</skip> <enableHtml>true</enableHtml> <enableXml>false</enableXml> </lint> </configuration> […]
We disable the XML output and enable HTML because it is more readable and we can get a better overview of HTML pages.
We just add android:lint
to the Maven commands with the following command:
$ mvn clean install android:lint
The results will be written to /target/lint-results/lint-results-html
.
You should get a result like the following:
[INFO] --- android-maven-plugin:3.9.0-rc.2:lint (default-cli) @ android-maven-project --- [INFO] Performing lint analysis. [INFO] Writing Lint HTML report in C:androidworkspace AndroidMavenProject argetlint-resultslint-results-html [INFO] Running command: …eclipseadt-bundle-windows-x86_64sdk oolslint.bat [INFO] with parameters: [--showall, --html, …workspace AndroidMavenProject argetlint-resultslint-results-html, --sources, …workspace AndroidMavenProjectsrc, …workspace AndroidMavenProject, --exitcode] [INFO] Lint analysis completed successfully.
It is possible to control lint invocation by adding failOnError
to the lint
tag.
If failOnError
is true
, any lint error (not warning) will stop the build. The default is set to false
. This flag is useful for continuous integration (see Chapter 5, Continuous Integration and Delivery with Maven) builds as it allows us to enforce lint's usage.
To increase lint's granularity, use the tag ignoreWarnings=true|false
.
If true, we don't report lint warnings, only errors are reported. By default, it is set to false
, as in warningsAsErrors=true|false
.
If true
, all lint warnings will be treated as errors. By default, it is set to false
.