關(guān)鍵詞:編譯-->DEX-->打包-->簽名和對(duì)齊
Android工程的編譯打包是個(gè)復(fù)雜的過(guò)程,期間既涉及到工程自身的源代碼、資源文件、AIDL文件,又涉及到工程所依賴(lài)的庫(kù)文件(Library, JAR, AAR)等,需要由多個(gè)工具分多個(gè)步驟完成。本文將對(duì)編譯打包的流程進(jìn)行描述,并對(duì)控制這個(gè)流程用到的gradle文件體系進(jìn)行介紹。
打包過(guò)程
下圖是谷歌官網(wǎng)給出的一個(gè)典型的apk構(gòu)建的過(guò)程,比較概括。主要包括兩個(gè)過(guò)程,首先是編譯過(guò)程,編譯的內(nèi)容包括本工程的文件以及依賴(lài)的各種庫(kù)文件,編譯的輸出包括dex文件和編譯后的資源文件。然后是打包過(guò)程。配合Keystore對(duì)第一步的輸出進(jìn)行簽名對(duì)齊,生成最終的apk文件。
下面這張圖對(duì)上面的步驟以及每步用到的工具進(jìn)行了細(xì)分,概括如下:
- Java編譯器對(duì)工程本身的java代碼進(jìn)行編譯,這些java代碼有三個(gè)來(lái)源:app的源代碼,由資源文件生成的R文件(aapt工具),以及有aidl文件生成的java接口文件(aidl工具)。產(chǎn)出為.class文件。
- .class文件和依賴(lài)的三方庫(kù)文件通過(guò)dex工具生成Delvik虛擬機(jī)可執(zhí)行的.dex文件,可能有一個(gè)或多個(gè),包含了所有的class信息,包括項(xiàng)目自身的class和依賴(lài)的class。產(chǎn)出為.dex文件。
- apkbuilder工具將.dex文件和編譯后的資源文件生成未經(jīng)簽名對(duì)齊的apk文件。這里編譯后的資源文件包括兩部分,一是由aapt編譯產(chǎn)生的編譯后的資源文件,二是依賴(lài)的三方庫(kù)里的資源文件。產(chǎn)出為未經(jīng)簽名的.apk文件。
- 分別由Jarsigner和zipalign對(duì)apk文件進(jìn)行簽名和對(duì)齊,生成最終的apk文件。
總結(jié)為:編譯-->DEX-->打包-->簽名和對(duì)齊
Gradle文件體系
Android工程通過(guò)gradle文件管理各項(xiàng)配置,gradle文件利用DSL(Domain Specific Language)語(yǔ)言描述配置,并使用Groovy語(yǔ)言處理編譯邏輯。一個(gè)典型的Android工程結(jié)構(gòu)如下:
在這里gradle文件分布在幾個(gè)不同的層級(jí),Project層級(jí)以及Module層級(jí)。
- Project層級(jí)的settings.gradle描述的是該P(yáng)roject包含哪些Module
include ':presentation', ':qamodel', ':chatcommonmodule', ':qa', ':unlimit'
Project層級(jí)的build.gradle描述的是作用于所有Module的配置,包括gradle版本等。
- Module層級(jí)的build.gradle。每個(gè)Module下都有一個(gè)作用于該Module的build.gradle文件,描述了該Module相關(guān)的配置。這些配置主要包括:BuildTypes,ProductFlavors,Dependency,SigningSettings等。
下面將簡(jiǎn)要介紹Module層級(jí)的build.gradle配置文件。
Configure Build Types
Module層級(jí)的gradle文件,buildTypes段。Android會(huì)自動(dòng)在buildTypes段創(chuàng)建release和debug兩類(lèi)配置,debug是默認(rèn)存在的,并且設(shè)置了debuggable true,默認(rèn)情況下不會(huì)展示出來(lái),除非你要修改debug的配置。如下:
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Configure Product Flavors
Module層級(jí)的gradle文件,productFlavors段。productFlavors的設(shè)置會(huì)自動(dòng)使用defaultConfig配置。如果設(shè)置了幾個(gè)不同的productFlavors,它們會(huì)共用defaultConfig配置,以及自己各自的配置,如applicationId。注意,不同的productFlavors都是通過(guò)manifest文件里的package屬性定義的名字來(lái)引用R文件,而不是使用各自的applicationId,所以applicationId其實(shí)是可以隨意取名的。
android {
...
defaultConfig {
applicationId "com.magic.wdl.simpledaggerdemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {...}
productFlavors {
demo {
applicationId "com.magic.wdl.simpledaggerdemo.demo"
versionName "1.0-demo"
}
full {
applicationId "com.magic.wdl.simpledaggerdemo.full"
versionName "1.0-full"
}
}
}
不同的build type和product Flavors可以互相組合,生成m*n種apk文件(不同的Build Variant[版本]),比如:
demoDebug
demoRelease
fullDebug
fullRelease
通過(guò) Build > Select Build Variant可以選擇要生成的apk類(lèi)型。
Configure dependency
dependencies段配置依賴(lài)的Module或是本地以及遠(yuǎn)端的binary。
dependencies {
// Module依賴(lài)
compile project(":mylibrary")
// 遠(yuǎn)端Binary依賴(lài)
compile 'com.android.support:appcompat-v7:23.4.0'
// 本地Binary依賴(lài),指定路徑app/libs/
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Configure signing settings
signingConfigs段配置簽名信息,生成簽名的方法參照這里。
signingConfigs {
release {
storeFile file("myreleasekey.keystore")
storePassword "password"
keyAlias "MyReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
參考:
https://developer.android.com/studio/build/index.html
http://www.alittlemadness.com/2010/06/07/understanding-the-android-build-process/
http://www.lxweimin.com/p/02dfa291d078
http://czak.pl/2016/05/31/handbuilt-android-project.html