本文是官網(wǎng)的個(gè)人簡(jiǎn)略版。
構(gòu)建過(guò)程
官網(wǎng)上的圖:
在生成最終的 APK 之前,packager 還會(huì)用 zipalign 來(lái)對(duì) app 進(jìn)行優(yōu)化以減少運(yùn)行時(shí)的占用內(nèi)存。
自定義構(gòu)建配置
利用 Gradle 和 Android 插件,可以從以下幾方面對(duì)編譯進(jìn)行配置:
- Build Types
通常用于不同開(kāi)發(fā)周期的配置,Android Studio 默認(rèn)會(huì)創(chuàng)建 debug 和 release 兩種編譯類(lèi)型。 - Product Flavors
用于為用戶(hù)提供不同的 app 版本,如免費(fèi)和收費(fèi)版。 - Build Variants
Gradle 用于編譯 app 的配置,build variant 由 build type 和 product flavor 共同產(chǎn)生。我們不直接配置 build variant,但通過(guò) build type 和 product flavor 將生成 build variant。 - Manifest Entries
我們可以在 build variant 配置(也就是 build type 和 product flavor 的配置)中指定 manifest 文件某些屬性的值,如應(yīng)用名、最小 SDK、target SDK 等。 - Dependencies
本地或遠(yuǎn)程依賴(lài)。 - Signing
在編譯配置中指定簽名設(shè)置并在構(gòu)建過(guò)程中自動(dòng)為 apk 簽名。 - ProGuard
可以為不同的 build variant 指定不同的混淆規(guī)則。 - Multiple APK Support
編譯不同的 apk,這些 apk 只包含特定屏幕尺寸或 abi 所需要的代碼和資源。
編譯配置文件
一個(gè) Android Studio 工程目錄如下:
在編譯配置文件中,普通文本文件使用 DSL(Domain Specific Language) 來(lái)描述配置,而操作編譯邏輯使用的 Groovy。
Gradle 設(shè)置文件
工程根目錄的 settings.gradle
用于告訴 Gradle 編譯時(shí)需要包含哪些 module。如:
include ‘:app’
頂層的編譯文件
工程根目錄的 build.gradle
文件,定義了應(yīng)用于工程中所有 module 的編譯配置。默認(rèn)的,它使用 buildscript
塊來(lái)確定所有 module 的 Gradle 倉(cāng)庫(kù)和依賴(lài)。
如:
/**
* buildscript 塊用于配置 Gradle 自身的倉(cāng)庫(kù)和依賴(lài)。
* 如它依賴(lài)的 Android plugin 將為 Gradle 提供編譯 Android app 模塊所需的額外指令。
*/
buildscript {
/**
* Gradle 搜索和下載依賴(lài)所用的倉(cāng)庫(kù)。Gradle 預(yù)配置的有 JCenter、MavenCentral、Ivy。
*/
repositories {
jcenter()
}
/**
* Gradle 編譯工程所需要的依賴(lài)。
*/
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
/**
* allprojects 塊用來(lái)配置所用 module 使用的倉(cāng)庫(kù)和依賴(lài)。
*/
allprojects {
repositories {
jcenter()
}
}
配置工程范圍的屬性
我們可以在頂層的 build.gradle
中添加一個(gè) ext
塊來(lái)配置額外屬性,這些屬性將在所有 module 中共享。
如:
buildscript {...}
allprojects {...}
// ext 塊包含自定義屬性并對(duì)所有 module 可用。
ext {
// The following are only a few examples of the types of properties you can define.
compileSdkVersion = 26
buildToolsVersion = "26.0.1"
// You can also create properties to specify versions for dependencies.
// Having consistent versions between modules can avoid conflicts with behavior.
supportLibVersion = "26.1.0"
...
}
...
在 module 的 build.gradle
文件中可以使用以下語(yǔ)法來(lái)訪問(wèn)這些屬性:
android {
// Use the following syntax to access properties you defined at the project level:
// rootProject.ext.property_name
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
...
}
...
dependencies {
compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
...
}
注意:應(yīng)避免這種用法,因?yàn)樗鼘?dǎo)致使用這些屬性的 module 耦合在一起。
Module 層的編譯文件
每一個(gè) module 目錄的 build.gradle
文件。
如:
/**
* 第一行將 Android plugin 應(yīng)用到編譯該 module 的 Gradle,這樣 android 塊才可用于指定 Android特定的編譯項(xiàng)。
*/
apply plugin: 'com.android.application'
/**
* android 塊用于配置所有的 Android 特定編譯項(xiàng)。
*/
android {
/**
* buildToolsVersion:SDK build tools 的版本。
*/
compileSdkVersion 26
buildToolsVersion "26.0.1"
/**
* The defaultConfig 塊包含了所有 build variant 的默認(rèn)配置,編譯系統(tǒng)可以動(dòng)態(tài)
* 覆蓋 main/AndroidManifest.xml 的默寫(xiě)屬性。我們也可以在 product flavors 中為不同版本的 app 重寫(xiě)這些值。
*/
defaultConfig {
/**
* 發(fā)布的包的唯一標(biāo)識(shí),但源碼仍會(huì)引用定義在 main/AndroidManifest.xml 文件中的包名。
*/
applicationId 'com.example.myapp'
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
/**
* buildTypes 塊用于配置多種 build type。
* 編譯系統(tǒng)默認(rèn)會(huì)定義兩種 build type:debug和release。debug 版本不會(huì)顯式地顯示在默認(rèn)的編譯配置中,但
* 它包含了調(diào)試工具并會(huì)使用 debug 密鑰進(jìn)行簽名。
* release 版本會(huì)使用混淆設(shè)置并且默認(rèn)沒(méi)有簽名。
* (這里指的是默認(rèn)生成的文件內(nèi)容,實(shí)際中往往會(huì)做修改,如為 release 配置簽名)
*/
buildTypes {
release {
minifyEnabled true // Enables code shrinking for the release build type.
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/**
* productFlavors 塊用于配置多種的 product flavors。編譯系統(tǒng)默認(rèn)生成的文件沒(méi)有創(chuàng)建這部分。
*/
productFlavors {
free {
applicationId 'com.example.myapp.free'
}
paid {
applicationId 'com.example.myapp.paid'
}
}
/**
* splits 塊配置不同的 apk 編譯,每一個(gè)將只包含所支持的屏幕尺寸或 abi 的源碼和資源。
*/
splits {
// 設(shè)置基于屏幕尺寸的 multiple apk
density {
// 是否編譯 multiple apk
enable false
// 在編譯 multiple apk 時(shí)排除這些密度
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
}
}
}
/**
* module 級(jí)別依賴(lài)
*/
dependencies {
compile project(":lib")
compile 'com.android.support:appcompat-v7:26.1.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Gradle 屬性文件
gradle.properties
配置工程范圍的 Gradle 設(shè)置,如 Gradle 進(jìn)程的最大堆大小。
local.properties
為編譯系統(tǒng)配置本地環(huán)境變量,如 SDK 安裝目錄。該目錄內(nèi)容一般由 Android Studio 自動(dòng)生成,所以通常不應(yīng)該手動(dòng)修改或者引入版本控制系統(tǒng)(不過(guò)因?yàn)闆](méi)必要引入 VCS 中,所以我們可以在這里配置簽名信息)。
Source Sets 源集
Android Studio將每一個(gè) module 的代碼和資源歸到一個(gè)源集中,一個(gè) module 的 main/
源集包含了所有 build variant 共用的代碼和資源。
我們可以為不同的 build variant 添加額外的源集目錄:
src/main/
src/buildType/
src/productFlavor/
src/productFlavorBuildType/
例如,在生成一個(gè)「fullDebug」版本應(yīng)用時(shí),編譯系統(tǒng)將從以下目錄合并代碼、設(shè)置、資源
-
src/fullDebug/
(build variant 源集) -
src/debug/
(build type 源集) -
src/full/
(product flavor 源集) -
src/main/
(main 源集)
如果不同源集中包含了同一文件的不同版本,Gradle 將采用以下的優(yōu)先級(jí)順序:
build variant > build type > product flavor > main source set > library dependencies
參考:
build process