轉:http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Tasks
Build Variants
There are two main use cases:
- Different versions of the same application
For instance, a free/demo version vs the “pro” paid application. - Same application packaged differently for multi-apk in Google Play Store.
See http://developer.android.com/google/play/publishing/multiple-apks.html for more information. - A combination of 1. and 2.
Product flavors
This new concept is designed to help when the differences are very minimum. If the answer to “Is this the same application?” is yes, then this is probably the way to go over Library Projects.
Product flavors are declared using a productFlavors DSL container:
android {....productFlavors {flavor1 {...}flavor2 {...}}}
Note: The name of the flavors cannot collide with existing Build Type names, or with the androidTest sourceSet.
Build Type + Product Flavor = Build Variant
Product Flavors do the same: the output of the project becomes all possible combinations of Build Types and, if applicable, Product Flavors.
Each (Build Type, Product Flavor) combination is called a Build Variant.
For instance, with the default debug and release Build Types, the above example generates four Build Variants:
- Flavor1 - debug
- Flavor1 - release
- Flavor2 - debug
- Flavor2 - release
Product Flavor Configuration
android {...defaultConfig {minSdkVersion 8versionCode 10}productFlavors {flavor1 {packageName "com.example.flavor1"versionCode 20}flavor2 {packageName "com.example.flavor2"minSdkVersion 14}}}
defaultConfig provides the base configuration for all flavors and each flavor can override any value. In the example above, the configurations end up being:
- flavor1
- packageName: com.example.flavor1
- minSdkVersion: 8
- versionCode: 20
- flavor2
- packageName: com.example.flavor2
- minSdkVersion: 14
- versionCode: 10
There are cases where a setting is settable on both the Build Type and the Product Flavor. In this case, it’s is on a case by case basis.
For instance, signingConfig is one of these properties.
This enables either having all release packages share the same SigningConfig, by setting android.buildTypes.release.signingConfig, or have each release package use their own SigningConfig by setting each android.productFlavors.*.signingConfig objects separately.
Sourcesets and Dependencies
The above example creates four sourceSets:
- android.sourceSets.flavor1
Location src/flavor1/ - android.sourceSets.flavor2
Location src/flavor2/ - android.sourceSets.androidTestFlavor1
Location src/androidTestFlavor1/ - android.sourceSets.androidTestFlavor2
Location src/androidTestFlavor2/
The following rules are used when dealing with all the sourcesets used to build a single APK:
- All source code (src/*/java) are used together as multiple folders generating a single output.
- Manifests are all merged together into a single manifest. This allows Product Flavors to have different components and/or permissions, similarly to Build Types.
- All resources (Android res and assets) are used using overlay priority where the Build Type overrides the Product Flavor, which overrides the main sourceSet.
- Each Build Variant generates its own R class (or other generated source code) from the resources. Nothing is shared between variants.
dependencies {flavor1Compile "..."}
- android.sourceSets.flavor1Debug
Location src/flavor1Debug/ - android.sourceSets.flavor1Release
Location src/flavor1Release/ - android.sourceSets.flavor2Debug
Location src/flavor2Debug/ - android.sourceSets.flavor2Release
Location src/flavor2Release/
Building and Tasks
When Product Flavors are used, more assemble-type tasks are created. These are:
- assemble<Variant Name>
- assemble<Build Type Name>
- assemble<Product Flavor Name>
#2 allows building all APKs for a given Build Type. For instance assembleDebug will build both Flavor1Debug and Flavor2Debug variants.
#3 allows building all APKs for a given flavor. For instance assembleFlavor1 will build both Flavor1Debug and Flavor1Release variants.
The task assemble will build all possible variants.
Testing
Testing multi-flavors project is very similar to simpler projects.The androidTest sourceset is used for common tests across all flavors, while each flavor can also have its own tests.
As mentioned above, sourceSets to test each flavor are created:
- android.sourceSets.androidTestFlavor1
Location src/androidTestFlavor1/ - android.sourceSets.androidTestFlavor2
Location src/androidTestFlavor2/
Similarly, those can have their own dependencies:
dependencies {androidTestFlavor1Compile "..."}
Each flavor has its own task to run tests: androidTest<VariantName>. For instance:
- androidTestFlavor1Debug
- androidTestFlavor2Debug
- assembleFlavor1Test
- installFlavor1Debug
- installFlavor1Test
- uninstallFlavor1Debug
- ...
The location of the test results and reports is as follows, first for the per flavor version, and then for the aggregated one:
- build/androidTest-results/flavors/<FlavorName>
- build/androidTest-results/all/
- build/reports/androidTests/flavors<FlavorName>
- build/reports/androidTests/all/
Multi-flavor variants
For instance, multi-apk support in Google Play supports 4 different filters. Creating different APKs split on each filter requires being able to use more than one dimension ofProduct Flavors.
Consider the example of a game that has a demo and a paid version and wants to use the ABI filter in the multi-apk support. With 3 ABIs and two versions of the application, 6 APKs needs to be generated (not counting the variants introduced by the different Build Types).
However, the code of the paid version is the same for all three ABIs, so creating simply 6 flavors is not the way to go.
Instead, there are two dimensions of flavors, and variants should automatically build all possible combinations.
This feature is implemented using Flavor Dimensions. Flavors are assigned to a specific dimension
android {...flavorDimensions "abi", "version"productFlavors {freeapp {flavorDimension "version"...}x86 {flavorDimension "abi"...}}}
From the following dimensioned Product Flavors [freeapp, paidapp] and [x86, arm, mips] and the [debug, release] Build Types, the following build variants will be created:
- x86-freeapp-debug
- x86-freeapp-release
- arm-freeapp-debug
- arm-freeapp-release
- mips-freeapp-debug
- mips-freeapp-release
- x86-paidapp-debug
- x86-paidapp-release
- arm-paidapp-debug
- arm-paidapp-release
- mips-paidapp-debug
- mips-paidapp-release
Each variant is configured by several Product Flavor objects:
- android.defaultConfig
- One from the abi dimension
- One from the version dimension
The flavor dimension is defined with higher priority first. So in this case:
abi > version > defaultConfig
- android.sourceSets.x86Freeapp
Location src/x86Freeapp/ - android.sourceSets.armPaidapp
Location src/armPaidapp/ - etc...
Advanced Build Customization
Running ProGuard
buildTypes {
release {
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
- proguard-android.txt
- proguard-android-optimize.txt
Shrinking Resources
Build options
Java Compilation options
android {compileOptions {sourceCompatibility = "1.6"targetCompatibility = "1.6"}}
android {aaptOptions {noCompress 'foo', 'bar'ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"}}
android {dexOptions {incremental false
preDexLibraries = false
jumboMode = false
javaMaxHeapSize "2048M"
}}
The classes task is the one that compile the Java source code.
It’s easy to access from build.gradle by simply using classes in a script. This is a shortcut for project.tasks.classes.
In Android projects, this is a bit more complicated because there could be a large number of the same task and their name is generated based on the Build Types and Product Flavors.
In order to fix this, the android object has two properties:
- applicationVariants (only for the app plugin)
- libraryVariants (only for the library plugin)
- testVariants (for both plugins)
Note that accessing any of these collections will trigger the creations of all the tasks. This means no (re)configuration should take place after accessing the collections.
The DomainObjectCollection gives access to all the objects directly, or through filters which can be convenient.
android.applicationVariants.all { variant ->....}
Property Name | Property Type | Description |
name | String | The name of the variant. Guaranteed to be unique. |
description | String | Human readable description of the variant. |
dirName | String | subfolder name for the variant. Guaranteed to be unique. Maybe more than one folder, ie “debug/flavor1” |
baseName | String | Base name of the output(s) of the variant. Guaranteed to be unique. |
outputFile | File | The output of the variant. This is a read/write property |
processManifest | ProcessManifest | The task that processes the manifest. |
aidlCompile | AidlCompile | The task that compiles the AIDL files. |
renderscriptCompile | RenderscriptCompile | The task that compiles the Renderscript files. |
mergeResources | MergeResources | The task that merges the resources. |
mergeAssets | MergeAssets | The task that merges the assets. |
processResources | ProcessAndroidResources | The task that processes and compile the Resources. |
generateBuildConfig | GenerateBuildConfig | The task that generates the BuildConfig class. |
javaCompile | JavaCompile | The task that compiles the Java code. |
processJavaResources | Copy | The task that process the Java resources. |
assemble | DefaultTask | The assemble anchor task for this variant. |
The ApplicationVariant class adds the following:
Property Name | Property Type | Description |
buildType | BuildType | The BuildType of the variant. |
productFlavors | List<ProductFlavor> | The ProductFlavors of the variant. Always non Null but could be empty. |
mergedFlavor | ProductFlavor | The merging of android.defaultConfig and variant.productFlavors |
signingConfig | SigningConfig | The SigningConfig object used by this variant |
isSigningReady | boolean | true if the variant has all the information needed to be signed. |
testVariant | BuildVariant | The TestVariant that will test this variant. |
dex | Dex | The task that dex the code. Can be null if the variant is a library. |
packageApplication | PackageApplication | The task that makes the final APK. Can be null if the variant is a library. |
zipAlign | ZipAlign | The task that zipaligns the apk. Can be null if the variant is a library or if the APK cannot be signed. |
install | DefaultTask | The installation task. Can be null. |
uninstall | DefaultTask | The uninstallation task. |
The LibraryVariant class adds the following:
Property Name | Property Type | Description |
buildType | BuildType | The BuildType of the variant. |
mergedFlavor | ProductFlavor | The defaultConfig values |
testVariant | BuildVariant | The Build Variant that will test this variant. |
packageLibrary | Zip | The task that packages the Library AAR archive. Null if not a library. |
The TestVariant class adds the following:
Property Name | Property Type | Description |
buildType | BuildType | The BuildType of the variant. |
productFlavors | List<ProductFlavor> | The ProductFlavors of the variant. Always non Null but could be empty. |
mergedFlavor | ProductFlavor | The merging of android.defaultConfig and variant.productFlavors |
signingConfig | SigningConfig | The SigningConfig object used by this variant |
isSigningReady | boolean | true if the variant has all the information needed to be signed. |
testedVariant | BaseVariant | The BaseVariant that is tested by this TestVariant. |
dex | Dex | The task that dex the code. Can be null if the variant is a library. |
packageApplication | PackageApplication | The task that makes the final APK. Can be null if the variant is a library. |
zipAlign | ZipAlign | The task that zipaligns the apk. Can be null if the variant is a library or if the APK cannot be signed. |
install | DefaultTask | The installation task. Can be null. |
uninstall | DefaultTask | The uninstallation task. |
connectedAndroidTest | DefaultTask | The task that runs the android tests on connected devices. |
providerAndroidTest | DefaultTask | The task that runs the android tests using the extension API. |
- ProcessManifest
- File manifestOutputFile
- AidlCompile
- File sourceOutputDir
- RenderscriptCompile
- File sourceOutputDir
- File resOutputDir
- MergeResources
- File outputDir
- MergeAssets
- File outputDir
- ProcessAndroidResources
- File manifestFile
- File resDir
- File assetsDir
- File sourceOutputDir
- File textSymbolOutputDir
- File packageOutputFile
- File proguardOutputFile
- GenerateBuildConfig
- File sourceOutputDir
- Dex
- File outputFolder
- PackageApplication
- File resourceFile
- File dexFile
- File javaResourceDir
- File jniDir
- File outputFile
- To change the final output file use "outputFile" on the variant object directly.
- ZipAlign
- File inputFile
- File outputFile
- To change the final output file use "outputFile" on the variant object directly.
The API for each task type is limited due to both how Gradle works and how the Android plugin sets them up.
This API is subject to change. In general the current API is around giving access to the outputs and inputs (when possible) of the tasks to add extra processing when required). Feedback is appreciated, especially around needs that may not have been foreseen.
For Gradle tasks (DefaultTask, JavaCompile, Copy, Zip), refer to the Gradle documentation.
BuildType and Product Flavor property reference
Using sourceCompatibility 1.7
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
minSdkVersion 7
targetSdkVersion 19
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
minSdkVersion
with a value earlier than 19, for all language features except try with resources. If you want to use try with resources, you will need to also use a minSdkVersion
of
19.