Why A New Build System?

  • Extensibility / Customization / Stable APIs
  • Unified across CI Servers and IDEs
  • Standart and advanced features
  • Current solutions (aka Ant, Maven) are not ideal

Why Gradle?

  • Powerful Build System
    • Declarative, Flexible
    • Imperative customization
    • Tooling API
  • Build System Toolkit
    • Plugins create own DSL, APIs, IDE integration
  • Free / Open Source

Gradle Basics

Simple Java Project

           
apply plugin: 'java'






        

Simple Android Project

           
buildscript {
    repositories { mavenCentral() }
    dependencies { classpath 'com.android.tools.build:gradle:0.5.+' }
}

apply plugin: 'android'


android {
    compileSdkVersion 17
    buildToolsVersion: '17.0.0'
}
            
        

Conventions: Source Folders

src/main/java
src/main/resources

src/test/java
src/test/resources

Conventions: Source Folders Android

src/main/AndroidManifest.xml
src/main/java
src/main/resources
src/main/res
src/main/assets
src/main/aidl
src/main/rs
src/main/jni


src/instrumentTest/java
src/instrumentTest/resources
src/instrumentTest/res
src/instrumentTest/assets
src/instrumentTest/aidl
src/instrumentTest/rs
src/instrumentTest/jni

Configuration for old projects

           
android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs ['src']
            res.srcDirs ['res']
        }
        
        instrumentTest.setRoot('tests')
    }
}
        

Configuration for old projects

           
android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs ['src']
            res.srcDirs ['res', 'res2']
        }
        
        instrumentTest.setRoot('tests')
    }
}
        

Gradle Tasks

$ cd myproject/
$ cd gradle <taskName1> [taskName2]


$ cd gradle tasks [--all]

Gradle Tasks

assemble


check




build
  -> assemble + check

clean

  jar   test

  findBugsMain
  findBugsTests

Gradle Tasks

assemble
  jar

check
  test
  findBugsMain
  findBugsTests

build
  -> assemble + check

clean

assemble


check
connectedCheck
deviceCheck


build
  -> assemble + check

clean

  assembleDebug + assembleRelease

Customization

Basic Customization


android {
    defaultConfig {
        versionCode 12
        versionName '2.0'
        
        minSdkVersion 14
        targetSdkVersion 17
    }
}
            

Basic Customization


def getVersionCode() {
    def code = ...
    return code
}

android {
    defaultConfig {
        versionCode getVersionCode()
        ...
    }
}
            

Build Types

  • Build/Packaging customization
    • debuggable flag
    • ProGuard
    • signing configuration
    • src/res overlays
  • Debug and release prebuild

Build Types: DSL


android {
    buildTypes {
        debug {
            packageNameSuffix '.debug'
            versionNameSuffix '-DEBUG'
        }
        beta {
            ...
        }   
    }
}
            

Build Types: Source Folders

src/main/AndroidManifest.xml
src/main/java
src/main/resources
src/main/res
src/main/assets
src/main/aidl
src/main/rs
src/main/jni


src/debug/...
src/beta/...
src/release/...


src/instrumentTest/java
src/instrumentTest/resources
src/instrumentTest/res
src/instrumentTest/assets
src/instrumentTest/aidl
src/instrumentTest/rs
src/instrumentTest/jni




Build Types: Tasks

assemble
  jar


check
  test
  findBugsMain
  findBugsTests

build
  -> assemble + check

clean

assemble
  assembleDebug + assembleBeta +   assembleRelease

check
connectedCheck
deviceCheck


build
  -> assemble + check

clean

  assembleDebug + assembleRelease

Signing Configuration


android {
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
        }
        
        // buildTypes.debug already configured
        // to use signingConfigs.debug
    }
}
            

Debuggable Release Builds


android {
    buildTypes {
        debugRelease.initWith(buildTypes.release)
        debugRelease {
            debuggable true
            packageNameSuffix '.debugrelease'
            signingConfig signingConfig.debug
        }
        sourceSets.debugRelease.setRoot('src/release')
    }
}
            

Manipulating the Model


android {
    ...
}

android.buildTypes.each { 
    type -> type.packageNameSuffix = ".$type.name"
}

            

Dependencies

Dependencies: Scopes

compile
runtime


testCompile
testRuntime





compile
apk


instrumentTestCompile
instrumentTestRuntime


debugCompile/Apk
releaseCompile/Apk
betaCompile/Apk

Local Dependencies


dependencies {
    compile fileTree(dir: 'libs', include '*.jar')
}

android {
    ...
}
            

Remote Dependencies


repositories { mavenCentral() }

dependencies {
    compile 'com.actionbarsherlock:actionbarsherlock:4.3.1'
    betaCompile file('libs/protobuf.jar')
}

android {
    ...
}
            

Multi-Project Setup


MyProject/
 | settings.gradle
 + app/
    | build.gradle
 + libs/
    + lib1/
       | build.gradle
    + lib2/
       | build.gradle
                    

    include ':app'
    include ':libs:lib1'
    include ':libs:lib2'  




 

                    

Project Dependencies


dependencies {
    compile project(':libs:lib1')
}

android {
    ...
}
            

Android Library Project



buildscript {
    repositories { mavenCentral() }
    dependencies { classpath 'com.android.tools.build:gradle:0.4' }
}

apply plugin: 'android-library'

android {
    compileSdkVersion 17
    buildToolsVersion: '17.0.0'
}
            

Android Library

  • Binary Bundle (.aar)
    • Uploadable to repositories
  • Support for
    • assets
    • ProGuard rules
    • Common Lint rules
    • ...

Build Variants

Build Flavors

  • Different versions of the same application
    • Paid vs Free
    • Multi .apk support in Google Play
  • Different Dimension(s) than Build Types

Product Flavors DSL


android {
    productFlavors {
        flavor1 {
            packageName 'com.example.flavor1'
            minSdkVersion 14
        }
        flavor2 {
            packageName 'com.example.flavor2'
        }
    }
}
            

Product Flavors: Source Folders

src/main/AndroidManifest.xml
src/main/java
src/main/resources
src/main/res
src/main/assets
src/main/aidl
src/main/rs
src/main/jni


src/debug/...
src/beta/...
src/release/...
src/flavor1/...


src/instrumentTest/java
src/instrumentTest/resources
src/instrumentTest/res
src/instrumentTest/assets
src/instrumentTest/aidl
src/instrumentTest/rs
src/instrumentTest/jni





src/instrumentTestFlavor1/...

Product Flavors: Dependency Scopes

compile
runtime


testCompile
testRuntime









compile
apk


instrumentTestCompile
instrumentTestRuntime


debugCompile/Package
releaseCompile/Package
betaCompile/Package


flavor1Compile/Package
instrumentTestFlavor1Compile/Package

Variant = Build Types * Product Flavor(s)

No Flavors:

debug release
debug release
- -


With Flavors:

debug release
Flavor1 Flavor1Debug Flavor1Release
Flavor2 Flavor2Debug Flavor2Release

Multi-Flavors DSL


android {
    flavorGroups 'abi', 'version'
    productFlavors {
        arm {
            flavorGroup 'abi'
        }
        paid {
            flavorGroup 'version'
            packageName '.paid'
        }
    }
}
            

Variant = Build Types * Product Flavor(s)

debug release
paid arm paid-arm-debug paid-arm-release
paid x86 paid-x86-debug paid-x86-release
paid mips paid-mips-debug paid-mips-release
free arm free-arm-debug free-arm-release
free x86 free-x86-debug free-x86-release
free mips free-mips-debug free-mips-release

Testing Recap

  • Test Source Sets: src/instrumentTest, src/instrumentTestFlavor1

  • Dependency Scopes: instrumentTestCompile, instrumentTestFlavor1Compile

  • Genearated AndroidManifest.xml

  • Only one Build Type is tested

  • Library embedded into Test APK

Testing Scenarios

  • check

  • connectedCheck

  • deviceCheck

Device Scenarios

  • Delayed / Queuded tests
    • Upload APKs to service
    • Queued tests
    • Remote report/dashboard

  • Test server API
    • Upload APKs method
    • Plugin register itself to the android plugin
    • Support any number of Servers

Device Scenarios

  • Devices Available on-demand
    • Direct connection to device
    • Local / Cloud emulators
    • Local report / dashboard

  • DeviceProvider / DeviceConnector API
    • Return list of DeviceConnectors
    • Connect, install, run tests, uninstall on each device
    • Support of any number of Providers

Build Environment

Build Environment

  • Gradle Version
    • Use the Wrapper!

  • Plugin Version
    • 'com.android.tools.buid:gradle:0.5'

  • Build Tools Version
    • android.buildToolsVersion '17.0'

  • IDE is not responsible for Builds

Usefull links

Thank You!

Presentation is available on github