The document discusses techniques for improving Android build processes using Gradle. It covers topics like using Gradle plugins, managing dependencies, flavors, testing, code quality tools, continuous integration, and publishing releases. The goal is to enable better code reuse, automation, and scaling of Android projects through an enhanced and standardized build system.
20. Level Up Your Android Build - droidcon Berlin 2015
Keep Up To Date
gw dependencyUpdates
The following dependencies have later milestone versions:
- com.fasterxml.jackson.core:jackson-annotations [2.1.2 -> 2.6.0-rc1]
- com.fasterxml.jackson.core:jackson-core [2.1.1 -> 2.6.0-rc1]
- com.fasterxml.jackson.core:jackson-databind [2.1.2 -> 2.6.0-rc1]
- com.github.kevinsawicki:http-request [4.0 -> 9.9]
- joda-time:joda-time [2.3 -> 2.8]
- org.mockito:mockito-core [1.9.0 -> 2.0.8-beta]
Generated report file build/dependencyUpdates/report.txt
21. Level Up Your Android Build - droidcon Berlin 2015
Code Quality Tools
apply plugin: 'checkstyle'
task checkstyleMain(type: Checkstyle) {
description 'Checks whether code complies with coding rules.'
ignoreFailures !project.failFastOnError
...
doLast {
if (project.hasProperty('checkstyle.html')) {
ant.xslt(in: reports.xml.destination,
style: file("$rulesDir/checkstyle/noframes-sorted.xsl"),
out: new File(reports.xml.destination.parent,
name - 'checkstyle' + '.html'))
}
}
}
22. Level Up Your Android Build - droidcon Berlin 2015
Code Quality Tools
apply plugin: 'checkstyle'
task checkstyleMain(type: Checkstyle) {
description 'Checks whether code complies with coding rules.'
ignoreFailures !project.failFastOnError
...
doLast {
if (project.hasProperty('checkstyle.html')) {
ant.xslt(in: reports.xml.destination,
style: file("$rulesDir/checkstyle/noframes-sorted.xsl"),
out: new File(reports.xml.destination.parent,
name - 'checkstyle' + '.html'))
}
}
}
gw checkstyleMain -PfailFastOnError -Pcheckstyle.html
23. Level Up Your Android Build - droidcon Berlin 2015
Code Quality Tools
apply plugin: 'checkstyle'
task checkstyleMain(type: Checkstyle) {
description 'Checks whether code complies with coding rules.'
ignoreFailures !project.failFastOnError
...
doLast {
if (project.hasProperty('checkstyle.html')) {
ant.xslt(in: reports.xml.destination,
style: file("$rulesDir/checkstyle/noframes-sorted.xsl"),
out: new File(reports.xml.destination.parent,
name - 'checkstyle' + '.html'))
}
}
}
24. Level Up Your Android Build - droidcon Berlin 2015
Continuous Integration
System.getenv("...")
Jenkins
BUILD_NUMBER
Travis
TRAVIS_BUILD_NUMBER
25. Level Up Your Android Build - droidcon Berlin 2015
Connected Tests on CI
task filterTestDevices << {
com.android.builder.testing.ConnectedDeviceProvider.metaClass
.getDevices = {
localDevices
.findAll { it.iDevice.online }
.findAll { !it.getProperty('ro.build.characteristics')
?.toLowerCase()?.contains('tablet') }
.unique { it.apiLevel }
}
}
26. Level Up Your Android Build - droidcon Berlin 2015
Connected Tests on CI
afterEvaluate {
project.tasks.findAll {
it.name.startsWith('connectedAndroidTest')
}*.dependsOn filterTestDevices
}
27. Level Up Your Android Build - droidcon Berlin 2015
Releasing from CI
● update Version
● commit changes
● upload to Stores
28. Level Up Your Android Build - droidcon Berlin 2015
Release from CI - Versioning
def versionFile = file('version.properties')
Version version = Version.read(versionFile)
task incrementVersion << {
Version.increment(versionFile)
}
29. Level Up Your Android Build - droidcon Berlin 2015
Release from CI - Versioning
def versionFile = file('version.properties')
Version version = Version.read(versionFile)
task incrementVersion << {
description = 'Increases the version'
Version.increment(versionFile)
}
buildSrc/
└── src
└── main
└── groovy
└── Version.groovy
30. Level Up Your Android Build - droidcon Berlin 2015
Release from CI - git
buildscript {
dependencies {
classpath 'org.ajoberstar:grgit:1.1.0'
}
}
ext {
git = org.ajoberstar.grgit.Grgit.open(
rootProject.file('.'))
}
def sha = git.head().abbreviatedId
git.add 'version.properties'
git.commit(message: "Bumping version to $VERSION_CODE")
git.push()
31. Level Up Your Android Build - droidcon Berlin 2015
Publishing - Google Play
play-publisher-plugin by triple-t
● bootstrapReleasePlayResources - Fetch all existing data from the Play
Store to bootstrap the required files and folders.
● publishApkRelease - Uploads the APK and the summary of recent
changes.
● publishListingRelease - Uploads the descriptions and images for the Play
Store listing.
● publishRelease - Uploads everything.
32. Level Up Your Android Build - droidcon Berlin 2015
Publishing - Google Play
play-publisher-plugin by triple-t
● bootstrapReleasePlayResources - Fetch all existing data from the Play
Store to bootstrap the required files and folders.
● publishApkRelease - Uploads the APK and the summary of recent
changes.
● publishListingRelease - Uploads the descriptions and images for the Play
Store listing.
● publishRelease - Uploads everything.play {
serviceAccountEmail = 'your-service-account-email'
pk12File = file('key.p12')
}
33. Level Up Your Android Build - droidcon Berlin 2015
Publishing - Other App Stores
task createAppDFs {
android.applicationVariants.all { variant ->
if (variant.buildType.name == "release")
createAppDF(variant.name)
}
}
34. Level Up Your Android Build - droidcon Berlin 2015
Advanced - Complex Build Scripts
share common configuration data via root subfolder
File shared(String relativeFilePath) {
file("shared/$relativeFilePath")
}
share common dependencies via root build.gradle
ext {
guavaDependency = 'com.google.guava:guava:18.0'
...
}
use it in sub-projects via:
dependencies {
compile guavaDependency
...
}
35. Level Up Your Android Build - droidcon Berlin 2015
Advanced - Shrink
dependencies {
classpath 'net.sf.proguard:proguard-gradle:4.11'
}
...
task shrinkGuava(type: proguard.gradle.ProGuardTask) {
injars configurations.injar.files
libraryjars configurations.libjar.files
outjars file("build/libs/guava_${guavaVersion}_base.jar")
configuration "guava.proguard"
}
guava.proguard:
-dontoptimize
-dontobfuscate
-keep public class com.google.common.base.** { public *; }
37. Level Up Your Android Build - droidcon Berlin 2015
Advanced - Sqlite Access
sqliteAccess {
migrationsDir 'src/main/assets/migrations'
packageName 'com.novoda.sqliteprovider.demo.simple'
generator { database, basedir ->
def access = access(database)
// …, adjust access model as needed
generateClass(file('code.template'), access, "DB",
packageName, basedir)
}
}
38. Level Up Your Android Build - droidcon Berlin 2015
Advanced - Sqlite Access
code.template
package $packageName;
public final class $className {
public static final class Tables {
<% access.tables.each { dataSet -> %>
public static final String $dataSet.name = "$dataSet.sqlName";
<% } %>
}
...
}
39. Level Up Your Android Build - droidcon Berlin 2015
Advanced - Groovy on Android
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
classpath 'org.codehaus.groovy:gradle-groovy-android-plugin:0.3.6'
}
}
apply plugin: 'groovyx.grooid.groovy-android'
dependencies {
compile 'org.codehaus.groovy:groovy:2.4.3:grooid'
}
40. Level Up Your Android Build - droidcon Berlin 2015
Resources (in order of appearance)
Android plugin for Gradle
https://developer.android.com/tools/building/plugin-for-gradle.html
gdub Tool
https://github.com/dougborg/gdub
apt Plugin
https://bitbucket.org/hvisser/android-apt
Command Plugin
https://github.com/novoda/gradle-android-command-plugin
Gradle Plugin Portal
http://plugins.gradle.org
41. Level Up Your Android Build - droidcon Berlin 2015
Resources (in order of appearance)
Proguard Annotation Squadleader
https://bitbucket.org/littlerobots/squadleader
Proguard Snippets
https://github.com/krschultz/android-proguard-snippets
Gradle Udacity Course
https://www.udacity.com/wiki/ud867
Groovy library for git
https://github.com/ajoberstar/grgit
42. Level Up Your Android Build - droidcon Berlin 2015
Resources (in order of appearance)
Soter Plugin
https://github.com/dlabs/soter
Shrink Guava Script Snippet
https://gist.github.com/devisnik/e54ea0a629adc82bcfa0
Groovy Android Plugin
https://github.com/groovy/groovy-android-gradle-plugin
Sqlite Analyzer Plugin
https://github.com/novoda/sqlite-analyzer
43. Level Up Your Android Build - droidcon Berlin 2015
TDTD - Tester-Driven Talk Development
Thanks to the folks from Android
Stammtisch Berlin for serving as Testers
for a lot of the presented material.
Upcoming book:
Growing Subject-Oriented Talks,
Guided by Testers
44. Level Up Your Android Build - droidcon Berlin 2015
Friedger Müffke Volker Leck
fmdroid devisnik
+FriedgerMüffke +VolkerLeck
friedger devisnik
45. Level Up Your Android Build - droidcon Berlin 2015
Build tooling
46. Level Up Your Android Build - droidcon Berlin 2015
Problems
● no re-use outside android app
● limited and manual code quality assurance (via test feedback)
● limited automation
○ manual versioning
○ manual deployment
○ no continuous integration
○ tedious distribution (beta channels, bug tracking, ..)
○ dependent on Android SDK installation
47. Level Up Your Android Build - droidcon Berlin 2015
Separation - Test Execution
test {
useJUnit {
excludeCategories 'com.sample.api.LiveTest'
}
}
task endpointTest(type: Test, dependsOn: testClasses) {
useJUnit {
includeCategories 'com.sample.api.LiveTest'
}
}
annotate tests with: @Category(LiveTest.class)