Building Android apps using Gradle
-
${PROJECT_ROOT}/gradle/wrapper/gradle-wrapper.properties
contains the keydistributionUrl
which embeds the version of Gradle to utilize near the end of the file. The next time the build wrapper is updated the new version will be pulled down. -
${PROJECT_ROOT}/build.gradle
- Controls the build environment && Anrdoid Gradle Plugin version. -
${PROJECT_ROOT}/app/build.gradle
- Controls the project specific build.- To have duel deployment of both the production application and the an indevelopment version, append a suffix to the target.
android { compileSdkVersion 19 buildToolsVersion "20.0.0" defaultConfig { applicationId "test.android.application" minSdkVersion 16 targetSdkVersion 19 } buildTypes { debug { applicationIdSuffix ".debug" } release { runProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } }
-
Automatic signing with Jenkins
Continous deployment is great, however quickly becomes difficult to do for Android due to the need to sign the application and push it into the Google Play Store. When using Jenkins you can easily allow the system to sign the application and push it up using the Google Play Android Publisher Plugin. The tricky part is getting the APK signed in a configurable way. Sure, you could just hardwire the configuration, however in the case Jenkins goes on strike I like to be able to build production APKs in other ways.
The following uses a project property to conditionally configure the release for signing. If the project property 'signing.config' is defined then the file pointed to will be loaded for the specified keys.
android { . . . signingConfigs { release { def singingConfig = project.properties.get("signing.config") if( singingConfig ){ logger.info("Using signing override.") Properties config = new Properties() File propertiesFile = new File( singingConfig ) propertiesFile.withInputStream { config.load(it) } storeFile file(config.keyStore) storePassword config.keyStorePassword keyAlias config.alias keyPassword config.secret } } } . . . buildTypes { ... release { signingConfig signingConfigs.release } ... } }
To ensure your configuration has been properly loaded you can use the follow:
gradlew -Psigning.config=/some/path/to/keys.properties signingConfig
. If your entires don't look like debug configurations (IE: contianing cryptographic checksums) something has gone wrong and your APKs will not be signed. Otherwise when you run the taskassembleRelease
the APK should be built intoapp/build/outputs/*-release.apk
.
- To have duel deployment of both the production application and the an indevelopment version, append a suffix to the target.
-
Jenkins build Pipeline
Ideal the appilcation build pipeline would be as follows for each variant:
-
Run unit tests for all variants
The unit tests reports can be picked up by the expression
app/build/test-results/**/*.xml
. -
Build and sign specific variant
To build and sign the production APK you can simply use
assemble${varient}
. For example, to build the standard relese version one would useassembleRelease
. Unless you have disabled Progaurd, you should probably archieve the mapping files usually contained underapp/build/outputs/mapping/${varient}
.When the above release configuration for Jenkins I would recommend using the goal
signingReport
to view the keys. -
Run automated acceptance tests
From here you can upload the APK into an emulator or onto an actual device to run automated acceptance tests against. Unforunately at this time I can't get ADB to run against on an SMP linux machine, so I couldn't get my Jenkins configuration to fully work.
-
Push APK to your target channel
There was an excellent plugin developed for Jenkins for this. The initial setup is Jenkins wide and only slightly painful when dealing with the Google Developer's Console and the Play Store Console. Once seutp with the proper API keys one could use the glob
**/build/outputs/*/*-${varient}.apk
to locate the APK to be published.
-