making the most of your gradle builds
TRANSCRIPT
Gradle Is Evolving!
● Gradle 3.0 released○ 75% faster Gradle Daemon, enabled by default
● Android Gradle plugin 2.3.0 released○ Build cache: faster clean builds
● Gradle Script Kotlin support
“Improving the performance of Gradle builds”
https://guides.gradle.org/performance/
Quick Improvements: Update Your Gradle
● Always try to use the latest Gradle version
● Latest at the moment○ Gradle: 3.4.1
○ Android Gradle plugin: 2.3.1
Quick Improvements: The Daemon
● Long-lived background process
● Enabled by default since Gradle 3.0○ Gradle 2: enable with org.gradle.daemon=true
● Disable on CI environments
● Disable with org.gradle.daemon=false in
gradle.properties (or --no-daemon)
● Stop with --stop
Quick Improvements: Parallel Execution
● Build independent subprojects in parallel
● Effect depends on project structure
● Enable with org.gradle.parallel=true
● Use with caution! Can lead to unexpected results
Configuring Build Scans
buildscript { repositories { maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "com.gradle:build-scan-plugin:1.6" }}
apply plugin: 'com.gradle.build-scan'
buildScan { licenseAgreementUrl = 'https://gradle.com/terms-of-service' licenseAgree = 'yes'}
<project-dir>/build.gradle
Use Plugins Wisely
● Every plugin adds to the build configuration time
● Remove those you don’t need!
Conditional Plugin Importing
if (project.hasProperty('dexCountEnabled')) { apply plugin: 'com.getkeepsafe.dexcount'}
./gradlew asD -PdexCountEnabled
Remove Unused Dependencies
● Affect dependency resolution time
● Bonus: decrease the dex method count!
Decrease Repository Count
Do not
allprojects {
repositories {
maven { url "..." }
jcenter()
mavenCentral()
maven { url "..." }
}
}
Do
allprojects {
repositories {
jcenter()
}
}
Exclude Build Variants
productFlavors {
qa { ... }
live { ... }
}
variantFilter { variant ->
def buildType = variant.buildType.name
def flavor = variant.flavors[0].name
if('release'.equals(buildType) && 'qa'.equals(flavor)) {
variant.ignore = true
}
}
Refactor Your Dependencies
dependencies.gradle
ext.versions = [
supportLibrary: '25.3.1'
]
ext.supportDependencies = [
appcompatv7 : "com.android.support:appcompat-v7:$versions.supportLibrary",
design : "com.android.support:design:$versions.supportLibrary",
recyclerviewv7: "com.android.support:recyclerview-v7:$versions.supportLibrary"
]
Refactor Your Dependencies
app/build.gradle
apply from: ‘../dependencies.gradle’
dependencies {
compile supportDependencies.appcompatv7
compile supportDependencies.design
compile supportDependencies.recyclerviewv7
}
Use “apply from”
jacoco.gradle
apply plugin: 'jacoco'
jacoco {
toolVersion = versions.jacoco
}
project.afterEvaluate {
...
}
app/build.gradle
apply from: '../jacoco.gradle'
Master Command Line
Print exception stacktrace (--stacktrace)
./gradlew assemble -s
Print INFO logs (--info)
./gradlew assemble -i
Print DEBUG logs (--debug)
./gradlew assemble -d
Master Command Line
Force offline execution
./gradlew assemble --offline
Force Gradle to re-download dependencies
./gradlew assemble --refresh-dependencies
Where Does a Dependency Come From?
Displays all dependencies declared in project
./gradlew -q :app:dependencies
Displays the Android dependencies of the project
./gradlew -q :app:androidDependencies
Getting More Insight
Displays the insight into a specific dependency in project
./gradlew -q :app:dependencyInsight --configuration compile --dependency okhttp
Use buildConfigFields
buildTypes {
debug {
...
buildConfigField 'long', 'UPDATE_FREQUENCY_MILLIS', '600000' // 10m
}
release {
...
buildConfigField 'long', 'UPDATE_FREQUENCY_MILLIS', '86400000' // 24h
}
}
Store Sensitive Info in gradle.properties
~/.gradle/gradle.properties
SuperSecretKey=this-is-a-super-secret-key
app/build.gradle
buildTypes.each {
it.buildConfigField 'String', 'SUPER_SECRET_KEY', SuperSecretKey
}
MainActivity.java
String secretKey = BuildConfig.SUPER_SECRET_KEY;
Exclude Resource Configurations
buildTypes { release { ... resConfigs "en", "de" }}
Limit resources to English and German localizations
Exclude Resource Configurations
buildTypes { release { ... resConfigs "auto" }}
Limit resources to project localizations
Share Test Code Between Test Types
android {
sourceSets {
String sharedTestDir = 'src/sharedTest/java'
test {
java.srcDir sharedTestDir
}
androidTest {
java.srcDir sharedTestDir
}
}
}
http://blog.danlew.net/2015/11/02/sharing-code-between-unit-tests-and-instrumentation-tests-on-android/
Thank You!Egor Andreevici
Software Developer at 1&1
blog.egorand.me | @EgorAnd | +EgorAndreevich