Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Gradle: From User to Addict

Gradle: From User to Addict

Default Gradle build scripts produced by Android IDEs are deceptively simple. However, this simplicity is often misleading as Gradle scripts have the potential for much more intricate behaviors than XML property file build systems. This complexity gap between the simple and the possible often causes roadblocks when an Android developer actually needs to do anything unique during a build. This class will help bridge that complexity gap by diving under the hood to explore how both simple and complicated build scripts actually work.

You will learn when and where lines of your build scripts are actually getting executed and what conditions prevent them from changing the state of your build. You'll also learn how you can create reusable code in a multi-app build environment. Finally, you'll hear important tips to make sure your Android Gradle scripts work well within the plugin ecosystem. All these lessons come straight from Jake's experiences developing the Crashlytics plugin for Gradle, which has been used in production by top Android app developers for almost two years. We'll cover advanced Gradle topics, but introduce them in a way that is accessible to newer users.

Jake Ouellette

April 09, 2015
Tweet

More Decks by Jake Ouellette

Other Decks in Programming

Transcript

  1. Knowledge Gap • “Where does this variable live?” • “When

    does this behavior happen?” • “How do others do what I want to do?”
  2. build.gradle apply plugin: 'android' android { compileSdkVersion 19 buildToolsVersion "19.0.3"

    defaultConfig { minSdkVersion 8 targetSdkVersion 19 versionCode 1 versionName "1.0" } buildTypes { release { runProguard false proguardFiles getDefaultProguardFile('proguard- android.txt'), 'proguard-rules.txt' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:19.+' }
  3. {?}

  4. configuration apply plugin: ‘android’ android { minSdkVersion 8 } apply

    plugin: ‘android’ android { minSdkVersion 8 }
  5. configuration apply plugin: ‘android’ android { minSdkVersion 8 } apply

    plugin: ‘android’ android { minSdkVersion 8 } execution :app:compileDebugAidl :app:compileDebugRenderscript :app:generateDebugBuildConfig :app:generateDebugAssets :app:mergeDebugAssets :app:generateDebugResValues :app:generateDebugResources :app:mergeDebugResources :app:processDebugManifest :app:processDebugResources :app:generateDebugSources :app:compileDebugJava :app:preDexDebug :app:dexDebug :app:processDebugJavaRes :app:validateDebugSigning :app:packageDebug :app:zipalignDebug :app:assembleDebug
  6. configuration apply plugin: ‘android’ android { minSdkVersion 8 } task

    print.doLast{ println(“Hi!”) } assemble.dependsOn(print) apply plugin: ‘android’ android { minSdkVersion 8 } task print.doLast{ println(“Hi!”) } assemble.dependsOn(print)
  7. configuration apply plugin: ‘android’ android { minSdkVersion 8 } task

    print.doLast{ println(“Hi!”) } assemble.dependsOn(print) apply plugin: ‘android’ android { minSdkVersion 8 } task print.doLast{ println(“Hi!”) } assemble.dependsOn(print) executed execution apply plugin: ‘android’ android { minSdkVersion 8 } task print.doLast{ println(“Hi!”) } assemble.dependsOn(print) :app:compileDebugRenderscript :app:generateDebugBuildConfig :app:generateDebugAssets :app:mergeDebugAssets :app:generateDebugResValues :app:generateDebugResources :app:mergeDebugResources :app:processDebugManifest :app:processDebugResources :app:generateDebugSources :app:compileDebugJava :app:preDexDebug :app:dexDebug :app:processDebugJavaRes :app:validateDebugSigning :app:packageDebug :app:zipalignDebug :app:print :app:assembleDebug
  8. configuration afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android

    { minSdkVersion 8 } afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android { minSdkVersion 8 }
  9. configuration afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android

    { minSdkVersion 8 } afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android { minSdkVersion 8 } evaluated afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android { minSdkVersion 8 }
  10. configuration afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android

    { minSdkVersion 8 } afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android { minSdkVersion 8 } evaluated execution afterEvaluate { println android.minSdkVersion } apply plugin: ‘android’ android { minSdkVersion 8 } :app:compileDebugRenderscript :app:generateDebugBuildConfig :app:generateDebugAssets :app:mergeDebugAssets :app:generateDebugResValues :app:generateDebugResources :app:mergeDebugResources :app:processDebugManifest :app:processDebugResources :app:generateDebugSources :app:compileDebugJava :app:preDexDebug :app:dexDebug :app:processDebugJavaRes :app:validateDebugSigning :app:packageDebug :app:zipalignDebug :app:assembleDebug
  11. org.gradle.api Interface Project All Superinterfaces: Comparable<Project>, ExtensionAware, PluginAware public interface

    Project extends Comparable<Project>, ExtensionAware, PluginAware This interface is the main API you use to interact with Gradle from your build file. From a Project, you have programmatic access to all of Gradle's features.
  12. org.gradle.api Interface Project All Superinterfaces: Comparable<Project>, ExtensionAware, PluginAware public interface

    Project extends Comparable<Project>, ExtensionAware, PluginAware This interface is the main API you use to interact with Gradle from your build file. From a Project, you have programmatic access to all of Gradle's features.
  13. Task task(Map<String,?> args, String name) Creates a Task with the

    given name and adds it to this project. Task task(Map<String,?> args, String name, Closure configureClosure) Creates a Task with the given name and adds it to this project. Task task(String name) Creates a Task with the given name and adds it to this project. Task task(String name, Closure configureClosure) Creates a Task with the given name and adds it to this project.
  14. apply plugin: ‘android’ android { minSdkVersion 8 } task print

    << { println(“Hi!”) } assemble.dependsOn(print)
  15. configuration apply plugin: ‘android’ android { minSdkVersion 8 } task

    print << { println(“Hi!”) } assemble.dependsOn(print) apply plugin: ‘android’ android { minSdkVersion 8 } task print << { println(“Hi!”) } assemble.dependsOn(print)
  16. configuration apply plugin: ‘android’ android { minSdkVersion 8 } task

    print << { println(“Hi!”) } assemble.dependsOn(print) apply plugin: ‘android’ android { minSdkVersion 8 } task print << { println(“Hi!”) } assemble.dependsOn(print) executed execution apply plugin: ‘android’ android { minSdkVersion 8 } task print << { println(“Hi!”) } assemble.dependsOn(print) :app:compileDebugRenderscript :app:generateDebugBuildConfig :app:generateDebugAssets :app:mergeDebugAssets :app:generateDebugResValues :app:generateDebugResources :app:mergeDebugResources :app:processDebugManifest :app:processDebugResources :app:generateDebugSources :app:compileDebugJava :app:preDexDebug :app:dexDebug :app:processDebugJavaRes :app:validateDebugSigning :app:packageDebug :app:zipalignDebug :app:print :app:assembleDebug
  17. build.gradle task emptyCopy(type: Copy) << { } COPY TASK HAS

    EMPTY SET OF THINGS TO COPY // CODE WILL NOT EXECUTE
  18. build.gradle task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename

    {it + System.currentTimeMillis()} } task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename {it + System.currentTimeMillis()} } task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename {it + System.currentTimeMillis()} } task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename {it + System.currentTimeMillis()} } task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename {it + System.currentTimeMillis()} } task copyTask(type: Copy) { from ‘build.gradle’ into ‘buildCache’ rename {it + System.currentTimeMillis()} }
  19. build.gradle class BuildCache implements Plugin<Project> { void apply(Project project) {

    // Create task. project.task(…) // Link task dependencies. assemble.dependsOn(…) }
  20. build.gradle class BuildCache implements Plugin<Project> { void apply(Project project) {

    // Create task. project.task(…) // Link task dependencies. assemble.dependsOn(…) } ‘cache’
  21. build.gradle class BuildCache implements Plugin<Project> { void apply(Project project) {

    // Create task. project.task(…) // Link task dependencies. assemble.dependsOn(…) } ‘cache’ Assemble Compile
  22. build.gradle class BuildCache implements Plugin<Project> { void apply(Project project) {

    // Create task. project.task(…) // Link task dependencies. project.android .applicationVariants.all { … } }
  23. 0.3 * System requirements: * Gradle 1.3+ (tested on 1.3/1.4).

    Will not be compatible with 1.5. An update will be required. * Android Platform Tools 16.0.2+ * New Features: * Renderscript support. * Support for multi resource folders. See 'multires' sample. * PNG crunch is now done incrementally and in parallel. * Support for multi asset folders. * Support for asset folders in Library Projects. * Support for versionName suffix provided by the BuildType. * Testing * Default sourceset for tests now src/instrumentTest (instrumentTest<Name> for flavors) * Instrumentation tests now: * started from "deviceCheck" instead of "check" * run on all connected devices in parallel. * break the build if any test fails. * generate an HTML report for each flavor/project, but also aggregated. * New plugin 'android-reporting' to aggregate android test results across projects. See 'flavorlib' sample. * Improved DSL: * replaced android.target with android.compileSdkVersion to make it less confusing with targetSdkVersion * signing information now a SigningConfig object reusable across BuildType and ProductFlavor * ability to relocate a full sourceSet. See 'migrated' sample. * API to manipulate Build Variants. * Fixes: * Default Java compile target set to 1.6. * Fix generation of R classes in case libraries share same package name as the app project. 0.2 * Fixed support for windows. * Added support for customized sourceset. (http://tools.android.com/tech-docs/new-build-system/using-the-new-build-system#TOC-Working-with-and-Customizing- SourceSets) * Added support for dependency per configuration. * Fixed support for dependency on local jar files. * New samples "migrated" and "flavorlib"
  24. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’
  25. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ apply plugin: ‘io.fabric’
  26. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’
  27. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’ apply plugin: ‘io.fabric’
  28. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’
  29. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’
  30. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ apply plugin: ‘io.fabric’
  31. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’
  32. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’ android.applicationVariants.all
  33. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’ apply plugin: ‘io.fabric’ android.applicationVariants.all
  34. build.gradle apply plugin: ‘com.android.application’ android { productFlavors { paid {

    } } } android.applicationVariants.all { variant -> // Rename package name } apply plugin: ‘io.fabric’ apply plugin: ‘com.android.application’ android { productFlavors { paid { } } } apply plugin: ‘io.fabric’ apply plugin: ‘io.fabric’ android.applicationVariants.all android.applicationVariants.all { variant -> // Rename package name }
  35. apply plugin: ‘com.android.application’ android { productFlavors { paid { }

    } } apply plugin: ‘io.fabric’ android.applicationVariants.all { variant -> // Rename package name }
  36. apply plugin: ‘com.android.application’ android { productFlavors { paid { }

    } } apply plugin: ‘io.fabric’ android.applicationVariants.all { variant -> // Rename package name }