android {
sourceSets {
main { // Encapsulates将包封 configurations for the main source set.
java.srcDirs = [‘other/java‘] // Changes the directory for Java sources. default is ‘src/main/java‘.
/** If you list multiple directories, Gradle uses all of them to collect sources. Because Gradle gives these directories equal priority, if you define the same resource in more than one directory, you get an error when merging resources. */
res.srcDirs = [‘other/res1‘, ‘other/res2‘] //default is ‘src/main/res‘
/** Note: You should avoid specifying a directory which is a 【parent】 to one or more other directories you specify. For example, avoid the following: res.srcDirs = [‘other/res1‘, ‘other/res1/layouts‘, ‘other/res1/strings‘]. You should specify either only the root ‘other/res1‘ directory, or only the nested ‘other/res1/layouts‘ and ‘other/res1/strings‘ directories. */
/** For each source set, you can specify only one Android manifest. By default, Android Studio creates a manifest for your main source set in the src/main/ directory. */
manifest.srcFile ‘other/AndroidManifest.xml‘
}
androidTest { // Create additional blocks to configure other source sets.
/** If all the files for a source set are located under a single root directory, you can specify that directory using the setRoot property. When gathering搜集 sources for the source set, Gradle looks only in locations relative to the root directory you specify. For example, after applying the configuration below for the androidTest source set, Gradle looks for Java sources only in the src/tests/java/ directory. */
setRoot ‘src/tests‘
}
}
}
21
21
1
android {
2
sourceSets {
3
main { // Encapsulates将包封 configurations for the main source set.
4
java.srcDirs= [‘other/java‘] // Changes the directory for Java sources. default is ‘src/main/java‘.
5
6
/** If you list multiple directories, Gradle uses all of them to collect sources. Because Gradle gives these directories equal priority, if you define the same resource in more than one directory, you get an error when merging resources. */
7
res.srcDirs= [‘other/res1‘, ‘other/res2‘] //default is ‘src/main/res‘
8
9
/** Note: You should avoid specifying a directory which is a 【parent】 to one or more other directories you specify. For example, avoid the following: res.srcDirs = [‘other/res1‘, ‘other/res1/layouts‘, ‘other/res1/strings‘]. You should specify either only the root ‘other/res1‘ directory, or only the nested ‘other/res1/layouts‘ and ‘other/res1/strings‘ directories. */
10
11
/** For each source set, you can specify only one Android manifest. By default, Android Studio creates a manifest for your main source set in the src/main/ directory. */
12
manifest.srcFile‘other/AndroidManifest.xml‘
13
}
14
15
androidTest { // Create additional blocks to configure other source sets.
16
17
/** If all the files for a source set are located under a single root directory, you can specify that directory using the setRoot property. When gathering搜集 sources for the source set, Gradle looks only in locations relative to the root directory you specify. For example, after applying the configuration below for the androidTest source set, Gradle looks for Java sources only in the src/tests/java/ directory. */
buildscript {...}
allprojects {...}
// This block encapsulates封装 custom properties and makes them available to all modules in the project.
ext {
// The following are only a few examples of the types of properties you can define.
compileSdkVersion = 26
// You can also create properties to specify versions for dependencies指定依赖项的版本.
// Having consistent一致的 versions between modules can avoid conflicts with behavior.
supportLibVersion = "27.1.1"
...
}
13
13
1
buildscript {...}
2
3
allprojects {...}
4
5
// This block encapsulates封装 custom properties and makes them available to all modules in the project.
6
ext {
7
// The following are only a few examples of the types of properties you can define.
8
compileSdkVersion=26
9
// You can also create properties to specify versions for dependencies指定依赖项的版本.
10
// Having consistent一致的 versions between modules can avoid conflicts with behavior.
android {
// Use the following syntax to access properties you defined at the project level: rootProject.ext.property_name
compileSdkVersion rootProject.ext.compileSdkVersion
}
dependencies {
compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
}
8
8
1
android {
2
// Use the following syntax to access properties you defined at the project level: rootProject.ext.property_name
android {...}
// Creates Gradle dependency configurations to use in the dependencies block.
configurations {
// For variants that combine a product flavor and build type, you need to intitialize a placeholder for its dependency configuration.
freeDebugRuntimeOnly{}
...
}
dependencies {
freeImplementation ‘com.google.firebase:firebase-ads:9.8.0‘ // Adds an implementation dependency only to the "free" product flavor.
freeDebugRuntimeOnly fileTree(dir: ‘libs‘, include: [‘*.jar‘]) // Adds a runtimeOnly dependency only to the "freeDebug" build variant.
testImplementation ‘junit:junit:4.12‘ // Adds a remote binary dependency only for local tests.
androidTestImplementation ‘com.android.support.test.espresso:espresso-core:3.0.2‘ // Adds a remote binary dependency only for the instrumented test APK.
}
15
15
1
android {...}
2
3
// Creates Gradle dependency configurations to use in the dependencies block.
4
configurations {
5
// For variants that combine a product flavor and build type, you need to intitialize a placeholder for its dependency configuration.
6
freeDebugRuntimeOnly{}
7
...
8
}
9
10
dependencies {
11
freeImplementation‘com.google.firebase:firebase-ads:9.8.0‘// Adds an implementation dependency only to the "free" product flavor.
12
freeDebugRuntimeOnlyfileTree(dir: ‘libs‘, include: [‘*.jar‘]) // Adds a runtimeOnly dependency only to the "freeDebug" build variant.
13
testImplementation‘junit:junit:4.12‘// Adds a remote binary dependency only for local tests.
14
androidTestImplementation‘com.android.support.test.espresso:espresso-core:3.0.2‘// Adds a remote binary dependency only for the instrumented test APK.
android {
splits {
density { // Configures multiple APKs based on screen density.
enable true // The default value is false
exclude "ldpi", "xxhdpi", "xxxhdpi" // Specifies a list of screen densities Gradle should not create multiple APKs for.
compatibleScreens ‘small‘, ‘normal‘, ‘large‘, ‘xlarge‘ // Specifies a list of compatible screen size settings for the manifest.
}
}
}
1
android {
2
splits {
3
density { // Configures multiple APKs based on screen density.
4
enabletrue// The default value is false
5
exclude"ldpi", "xxhdpi", "xxxhdpi"// Specifies a list of screen densities Gradle should not create multiple APKs for.
6
compatibleScreens‘small‘, ‘normal‘, ‘large‘, ‘xlarge‘// Specifies a list of compatible screen size settings for the manifest.
android {
splits {
abi { // Configures multiple APKs based on ABI.
enable true // The default value is false
// By default all ABIs are included, so use reset() and include to specify that we only want APKs for x86 and x86_64.
reset() // Resets the list of ABIs that Gradle should create APKs for to none.
include "x86", "x86_64" // Specifies a list of ABIs that Gradle should create APKs for.
universalApk false // Specifies that we do not want to also generate a universal APK that includes all ABIs.
}
}
}
1
android {
2
splits {
3
abi { // Configures multiple APKs based on ABI.
4
enabletrue// The default value is false
5
// By default all ABIs are included, so use reset() and include to specify that we only want APKs for x86 and x86_64.
6
reset() // Resets the list of ABIs that Gradle should create APKs for to none.
7
include"x86", "x86_64"// Specifies a list of ABIs that Gradle should create APKs for.
8
universalApkfalse// Specifies that we do not want to also generate a universal APK that includes all ABIs.
9
}
10
}
11
}
配置动态版本代码
[Configure dynamic version codes]
默认情况下,在 Gradle 为您的项目生成 APK 时,每个 APK 都有相同的版本信息,此信息在模块级build.gradle文件中指定。由于 Google Play 商店不允许同一个应用的多个 APK 全都具有相同的版本信息,在上传到 Play 商店之前,您需要确保每个 APK 都有自己唯一的versionCode。
为此,您可以使用自定义构建逻辑在构建时向每个 APK 分配不同的版本代码。例如,在为每个 ABI 创建单独的 APK 时,自动 APK 版本控制将如下所示:
ext.abiCodes = [‘armeabi-v7a‘:1, x86:2, x86_64:3] // ext.densityCodes = [‘xdpi‘: 1, ‘xxhdpi‘: 2, ‘xxxhdpi‘: 3]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output -> // Assigns a different version code for each output APK other than the universal APK.
def baseAbiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))// Determines the ABI for this variant and returns the mapped value.
/** Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, the following code does not override the version code for universal APKs. However, because we want universal APKs to have the lowest version code, this outcome is desirable令人满意的. */
if (baseAbiVersionCode != null) {
/** Assigns the new version code to versionCodeOverride, which changes the version code for only the output APK, not for the variant itself. Skipping this step simply causes只会导致 Gradle to use the value of variant.versionCode for the APK. */
output.versionCodeOverride = baseAbiVersionCode * 1000 + variant.versionCode
}
}
}
variant.outputs.each { output->// Assigns a different version code for each output APK other than the universal APK.
6
defbaseAbiVersionCode=project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))// Determines the ABI for this variant and returns the mapped value.
7
8
/** Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, the following code does not override the version code for universal APKs. However, because we want universal APKs to have the lowest version code, this outcome is desirable令人满意的. */
9
if (baseAbiVersionCode!=null) {
10
/** Assigns the new version code to versionCodeOverride, which changes the version code for only the output APK, not for the variant itself. Skipping this step simply causes只会导致 Gradle to use the value of variant.versionCode for the APK. */
某些情况下,您可能希望组合多个产品风味中的配置。为此,您可以通过 Android Plugin for Gradle 创建产品风味组,称为风味维度。
下面的代码示例使用flavorDimensions属性创建一个“模式”风味维度以组织“完整”和“演示”产品风味,以及一个“api”风味维度以基于 API 级别组织产品风味配置。随后,Gradle 会将“模式”维度的产品风味与“api”维度的产品风味组合。
android {
buildTypes {
debug {...}
release {...}
}
/** Specifies指定 the flavor dimensions you want to use. The order in which you list each dimension determines决定了 its priority优先级, from highest to lowest, when Gradle merges合并 variant sources and configurations. You must assign分配给 each product flavor you configure to one of the flavor dimensions. */
flavorDimensions "api", "mode"
productFlavors {
demo {
dimension "mode" // Assigns this product flavor to the "mode" flavor dimension.
}
full {
dimension "mode"
}
/** Configurations in the "api" product flavors override覆盖 those in "mode" flavors and the defaultConfig {} block. Gradle determines确定 the priority between flavor dimensions based on根据 the order in which they appear next to the flavorDimensions property above--the first dimension has a higher priority than the second, and so on. */
minApi24 {
dimension "api"
minSdkVersion ‘24‘
/** To ensure the target device receives the version of the app with the highest compatible API level[要确保目标设备接收具有最高兼容API级别的应用程序版本], assign分配 version codes in increasing value with API level. */
versionCode 30000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi24"
}
minApi23 {
dimension "api"
minSdkVersion ‘23‘
versionCode 20000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi23"
}
minApi21 {
dimension "api"
minSdkVersion ‘21‘
versionCode 10000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi21"
}
}
}
...
43
1
android {
2
buildTypes {
3
debug {...}
4
release {...}
5
}
6
7
/** Specifies指定 the flavor dimensions you want to use. The order in which you list each dimension determines决定了 its priority优先级, from highest to lowest, when Gradle merges合并 variant sources and configurations. You must assign分配给 each product flavor you configure to one of the flavor dimensions. */
8
flavorDimensions"api", "mode"
9
10
productFlavors {
11
demo {
12
dimension"mode"// Assigns this product flavor to the "mode" flavor dimension.
13
}
14
15
full {
16
dimension"mode"
17
}
18
19
/** Configurations in the "api" product flavors override覆盖 those in "mode" flavors and the defaultConfig {} block. Gradle determines确定 the priority between flavor dimensions based on根据 the order in which they appear next to the flavorDimensions property above--the first dimension has a higher priority than the second, and so on. */
20
minApi24 {
21
dimension"api"
22
minSdkVersion‘24‘
23
/** To ensure the target device receives the version of the app with the highest compatible API level[要确保目标设备接收具有最高兼容API级别的应用程序版本], assign分配 version codes in increasing value with API level. */
android {
lintOptions {
disable ‘TypographyFractions‘,‘TypographyQuotes‘ // Turns off checks for the issue IDs you specify.
enable ‘RtlHardcoded‘, ‘RtlCompat‘, ‘RtlEnabled‘ // These checks are in addition to the default lint checks.
/** To enable checks for only a subset of issue IDs and ignore all others, list the issue IDs with the ‘check‘ property instead. This property overrides any issue IDs you enable or disable using the properties above. */
check ‘NewApi‘, ‘InlinedApi‘
quiet true // If set to true, turns off analysis progress reporting by lint.
abortOnError false // if set to true (default), stops the build if errors are found.
ignoreWarnings true // if true, only report errors.
}
}
1
android {
2
lintOptions {
3
disable‘TypographyFractions‘,‘TypographyQuotes‘// Turns off checks for the issue IDs you specify.
4
enable‘RtlHardcoded‘, ‘RtlCompat‘, ‘RtlEnabled‘// These checks are in addition to the default lint checks.
5
/** To enable checks for only a subset of issue IDs and ignore all others, list the issue IDs with the ‘check‘ property instead. This property overrides any issue IDs you enable or disable using the properties above. */
6
check‘NewApi‘, ‘InlinedApi‘
7
quiettrue// If set to true, turns off analysis progress reporting by lint.
8
abortOnErrorfalse// if set to true (default), stops the build if errors are found.
android {
defaultConfig {
testApplicationId "com.test.foo" // Specifies the application ID for the test APK.
testInstrumentationRunner "android.test.InstrumentationTestRunner" // fully-qualified class name
// If set to ‘true‘, enables the instrumentation class to start and stop profiling.
// If set to false (default), profiling occurs the entire time the instrumentation class is running.
testHandleProfiling true
// If set to ‘true‘, indicates that the Android system should run the instrumentation class as a functional test.
testFunctionalTest true //The default value is ‘false‘
}
}
1
android {
2
defaultConfig {
3
testApplicationId"com.test.foo"// Specifies the application ID for the test APK.
4
testInstrumentationRunner"android.test.InstrumentationTestRunner"// fully-qualified class name
5
// If set to ‘true‘, enables the instrumentation class to start and stop profiling.
6
// If set to false (default), profiling occurs the entire time the instrumentation class is running.
7
testHandleProfilingtrue
8
// If set to ‘true‘, indicates that the Android system should run the instrumentation class as a functional test.
9
testFunctionalTesttrue//The default value is ‘false‘
android {
testOptions {
// ‘$rootDir‘ sets the path relative to the root directory of the current project.
reportDir "$rootDir/test-reports" //默认在 project/module_name/build/outputs/reports/
resultsDir "$rootDir/test-results" //默认在 project/module_name/build/outputs/test-results/
}
}
9
1
android {
2
testOptions {
3
// ‘$rootDir‘ sets the path relative to the root directory of the current project.
android {
testOptions {
unitTests {
/** By default, local unit tests throw an exception any time the code you are testing tries to access Android platform APIs (unless you mock嘲笑、藐视、不尊重 Android dependencies yourself or with a testing framework like Mockito). However, you can enable the following property so that the test returns either null or zero when accessing platform APIs, rather than throwing an exception. */
returnDefaultValues true
all { // controlling how Gradle executes local unit tests.
jvmArgs ‘-XX:MaxPermSize=256m‘ // Sets JVM argument(s) for the test JVM(s).
if (it.name == ‘testDebugUnitTest‘) { // You can also check the task name to apply options to only the tests you specify.
systemProperty ‘debug‘, ‘true‘
}
}
}
}
}
1
android {
2
testOptions {
3
unitTests {
4
/** By default, local unit tests throw an exception any time the code you are testing tries to access Android platform APIs (unless you mock嘲笑、藐视、不尊重 Android dependencies yourself or with a testing framework like Mockito). However, you can enable the following property so that the test returns either null or zero when accessing platform APIs, rather than throwing an exception. */
5
returnDefaultValuestrue
6
7
all { // controlling how Gradle executes local unit tests.
8
jvmArgs‘-XX:MaxPermSize=256m‘// Sets JVM argument(s) for the test JVM(s).
9
if (it.name==‘testDebugUnitTest‘) { // You can also check the task name to apply options to only the tests you specify.
10
systemProperty‘debug‘, ‘true‘
11
}
12
}
13
}
14
}
15
}
优化您的构建
[Optimize your build]
本部分将介绍一些有助于加快您的完整构建和增量构建速度的配置。
压缩代码
[Shrink your code]
Android Studio 使用 ProGuard 来压缩代码。对于新项目,Android Studio 将使用 Android SDKtools/proguard/folder下的默认设置文件 proguard-android.txt。要想进一步压缩代码,请尝试使用位于同一位置的proguard-android-optimize.txt文件。
android {
dexOptions {
maxProcessCount 8 // Sets the maximum number of DEX processes that can be started concurrently.
javaMaxHeapSize "2g" // Sets the maximum memory allocation pool size for the dex operation.
preDexLibraries true // Enables Gradle to pre-dex library dependencies.
}
}
1
android {
2
dexOptions {
3
maxProcessCount8// Sets the maximum number of DEX processes that can be started concurrently.
4
javaMaxHeapSize"2g"// Sets the maximum memory allocation pool size for the dex operation.
5
preDexLibrariestrue// Enables Gradle to pre-dex library dependencies.
def keystorePropertiesFile = rootProject.file("keystore.properties") // Creates and initializes a variable to the keystore.properties file.
def keystoreProperties = new Properties() // Initializes a new Properties() object
keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) // Loads the keystore.properties file into the Properties object.
android { ... }
1
defkeystorePropertiesFile=rootProject.file("keystore.properties") // Creates and initializes a variable to the keystore.properties file.
2
defkeystoreProperties=newProperties() // Initializes a new Properties() object
3
keystoreProperties.load(newFileInputStream(keystorePropertiesFile)) // Loads the keystore.properties file into the Properties object.
android {
buildTypes {
release {
// These values are defined only for the release build, which is typically典型的 used for 【full builds】 and 【continuous builds】.
buildConfigField("String", "BUILD_TIME", ""${minutesSinceEpoch}"")
resValue("string", "build_time", "${minutesSinceEpoch}")
}
debug {
// Use static values for incremental builds to ensure that resource files and BuildConfig aren‘t rebuilt重建 with each run.
// If they were dynamic, they would prevent阻止 certain某一、某些 benefits利益、福利、优势 of Instant Run as well as Gradle UP-TO-DATE checks.
buildConfigField("String", "BUILD_TIME", ""0"")
resValue("string", "build_time", "0")
}
}
}
1
android {
2
buildTypes {
3
release {
4
// These values are defined only for the release build, which is typically典型的 used for 【full builds】 and 【continuous builds】.
android {
defaultConfig {
def filesAuthorityValue = applicationId + ".files" // Creates a property for the FileProvider authority.
// Creates a placeholder property to use in the manifest.
manifestPlaceholders = [filesAuthority: filesAuthorityValue,
app_logo : "@drawable/icon",
app_channel_value: "小米应用市场",
]
// Adds a new field for the authority to the BuildConfig class.
buildConfigField("String", "FILES_AUTHORITY", ""${filesAuthorityValue}"")
buildConfigField "String", "BASE_URL", ‘"http://120.com/"‘
buildConfigField "int", "countryCode", "20094"
}
}
9
10
1
android {
2
defaultConfig {
3
deffilesAuthorityValue=applicationId+".files"// Creates a property for the FileProvider authority.
4
5
// Creates a placeholder property to use in the manifest.