首先獻(xiàn)上官方文檔https://developer.android.google.cn/studio/build/gradle-tips
首先我們明確一下Android 的打包流程
https://developer.android.google.cn/studio/build/index.html
1充尉、編譯器①將安卓的源碼編譯為DEX文件,并將其他內(nèi)容轉(zhuǎn)為②已編譯資源醋界。
2教硫、APK打包器將 DEX 文件與已編譯資源合并③成為單個(gè) APK。
3宋列、APK打包器使用調(diào)試或發(fā)布秘鑰庫(kù)簽名④ APK昭抒。
4、APK打包器使用 zipalign⑤對(duì)其進(jìn)行優(yōu)化炼杖。
結(jié)束構(gòu)建灭返。
這里有五個(gè)問題:
1、編譯器將.java 編譯為 dex 文件的過(guò)程是怎樣的坤邪;
2熙含、其他內(nèi)容如何轉(zhuǎn)為已編譯資源的;
3艇纺、APK打包器如何將 dex 與已編譯資源合并為 apk 的怎静;
4、如何進(jìn)行簽名操作喂饥;
5消约、zipalign 是什么,以及如何對(duì) apk 進(jìn)行了優(yōu)化员帮;
project 層級(jí)的 build.gradle
/**
* 您可以在buildscript塊中為Gradle本身配置存儲(chǔ)庫(kù)和依賴項(xiàng)或粮,
* 這意味著您不應(yīng)在此處包含模塊的依賴項(xiàng)。
* 例如捞高,此塊包含Gradle的Android插件作為依賴項(xiàng)氯材,
* 因?yàn)樗峁┝薌radle構(gòu)建Android應(yīng)用程序模塊所需的其他指令。
*/
buildscript {
/**
* repositories塊配置Gradle使用的repositories搜索或下載依賴項(xiàng)硝岗。
* Gradle預(yù)先配置對(duì)遠(yuǎn)程的支持存儲(chǔ)庫(kù)氢哮,如JCenter,Maven Central和Ivy型檀。 您也可以使用本地
* 存儲(chǔ)庫(kù)或定義您自己的遠(yuǎn)程存儲(chǔ)庫(kù)冗尤。
* 下面的代碼定義JCenter作為存儲(chǔ)庫(kù)Gradle應(yīng)該用來(lái)查找它的依賴項(xiàng)。
* 使用Android Studio 3.0及更高版本創(chuàng)建的新項(xiàng)目還包括Google的Maven存儲(chǔ)庫(kù)胀溺。
*/
repositories {
google()
jcenter()
}
/**
* dependencies塊配置Gradle需要用于構(gòu)建項(xiàng)目的依賴項(xiàng)裂七。
* 以下行將Gradle版本3.4.0的Android插件添加為類路徑依賴項(xiàng)。
*/
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
}
}
/**
* allprojects塊是您配置項(xiàng)目中所有模塊使用的存儲(chǔ)庫(kù)和依賴項(xiàng)的方仓坞,
* 例如第三方插件或庫(kù)背零。
* 但是,您應(yīng)該在每個(gè)模塊級(jí)build.gradle文件中配置特定于模塊的賴項(xiàng)无埃。
* 對(duì)于新項(xiàng)目徙瓶,Android Studio默認(rèn)包含JCenter和Google的Maven存儲(chǔ)庫(kù)毛雇,
* 但它不配置任何依賴項(xiàng)(除非您選擇需要某些模板的模板)。
*/
allprojects {
repositories {
google()
jcenter()
}
}
APP 下的 build.gradle基本結(jié)構(gòu)
/**
* The first line in the build configuration applies the Android plugin for
* Gradle to this build and makes the android block available to specify
* Android-specific build options.
*/
apply plugin: 'com.android.application'
/**
* The android block is where you configure all your Android-specific
* build options.
*/
android {
/**
* compileSdkVersion specifies the Android API level Gradle should use to
* compile your app. This means your app can use the API features included in
* this API level and lower.
*/
compileSdkVersion 28
/**
* buildToolsVersion specifies the version of the SDK build tools, command-line
* utilities, and compiler that Gradle should use to build your app. You need to
* download the build tools using the SDK Manager.
*
* This property is optional because the plugin uses a recommended version of
* the build tools by default.
*/
buildToolsVersion "28.0.3"
/**
* The defaultConfig block encapsulates default settings and entries for all
* build variants, and can override some attributes in main/AndroidManifest.xml
* dynamically from the build system. You can configure product flavors to override
* these values for different versions of your app.
*/
defaultConfig {
/**
* applicationId uniquely identifies the package for publishing.
* However, your source code should still reference the package name
* defined by the package attribute in the main/AndroidManifest.xml file.
*/
applicationId 'com.example.myapp'
// Defines the minimum API level required to run the app.
minSdkVersion 15
// Specifies the API level used to test the app.
targetSdkVersion 28
// Defines the version number of your app.
versionCode 1
// Defines a user-friendly version name for your app.
versionName "1.0"
}
/**
* The buildTypes block is where you can configure multiple build types.
* By default, the build system defines two build types: debug and release. The
* debug build type is not explicitly shown in the default build configuration,
* but it includes debugging tools and is signed with the debug key. The release
* build type applies Proguard settings and is not signed by default.
*/
buildTypes {
/**
* By default, Android Studio configures the release build type to enable code
* shrinking, using minifyEnabled, and specifies the Proguard settings file.
*/
release {
minifyEnabled true // Enables code shrinking for the release build type.
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/**
* The productFlavors block is where you can configure multiple product flavors.
* This allows you to create different versions of your app that can
* override the defaultConfig block with their own settings. Product flavors
* are optional, and the build system does not create them by default.
*
* This example creates a free and paid product flavor. Each product flavor
* then specifies its own application ID, so that they can exist on the Google
* Play Store, or an Android device, simultaneously.
*
* If you declare product flavors, you must also declare flavor dimensions
* and assign each flavor to a flavor dimension.
*/
flavorDimensions "tier"
productFlavors {
free {
dimension "tier"
applicationId 'com.example.myapp.free'
}
paid {
dimension "tier"
applicationId 'com.example.myapp.paid'
}
}
/**
* The splits block is where you can configure different APK builds that
* each contain only code and resources for a supported screen density or
* ABI. You'll also need to configure your build so that each APK has a
* different versionCode.
*/
splits {
// Settings to build multiple APKs based on screen density.
density {
// Enable or disable building multiple APKs.
enable false
// Exclude these densities when building multiple APKs.
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
}
}
}
/**
* The dependencies block in the module-level build configuration file
* specifies dependencies required to build only the module itself.
* To learn more, go to Add build dependencies.
*/
dependencies {
implementation project(":lib")
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
1侦镇、android插件的引入灵疮,使得 android{}部分可用
2、android 配置
3虽缕、dependences 依賴配置
首先來(lái)看 android {}部分
我們看看都支持哪些配置字段:
aaptOptions {}//指定Android資產(chǎn)包裝工具(AAPT)的選項(xiàng)始藕。
adbOptions {}//指定Android調(diào)試橋(ADB)的選項(xiàng)蒲稳,例如APK安裝選項(xiàng)氮趋。
buildTypes {}//封裝此項(xiàng)目的所有構(gòu)建類型配置。
compileOptions {}//指定Java編譯器選項(xiàng)江耀,例如Java源代碼的語(yǔ)言級(jí)別和生成的字節(jié)碼剩胁。
dataBinding {}//指定數(shù)據(jù)綁定庫(kù)的選項(xiàng)。
defaultConfig {}//指定Android插件適用于所有構(gòu)建變體的變體屬性的默認(rèn)值祥国。
dexOptions {}//指定DEX工具的選項(xiàng)昵观,例如啟用庫(kù)預(yù)處理。
externalNativeBuild {}//使用CMake或ndk-build配置外部本機(jī)構(gòu)建舌稀。
jacoco {}//配置用于脫機(jī)檢測(cè)和覆蓋率報(bào)告的JaCoCo版本啊犬。
lintOptions {}//指定lint工具的選項(xiàng)。
packagingOptions {}//指定用于確定Android插件將哪些文件打包到APK中的選項(xiàng)和規(guī)則壁查。
productFlavors {}//封裝此項(xiàng)目的所有產(chǎn)品風(fēng)格配置觉至。
簽名會(huì)話{}//封裝可應(yīng)用于BuildType和ProductFlavor配置的簽名配置。
sourceSets {}//封裝所有變體的源集配置睡腿。
splits{}//指定用于構(gòu)建多個(gè)APK或APK拆分的配置语御。
testOptions {}//指定Android插件應(yīng)如何運(yùn)行本地和檢測(cè)測(cè)試的選項(xiàng)。
詳細(xì)說(shuō)明祭出 google 文檔 plugins:'com.android.application'
挑幾個(gè)常用的說(shuō)一下
首先新建項(xiàng)目時(shí)自動(dòng)會(huì)生成的 defaultConfig{}
指定Android插件適用于所有構(gòu)建變體的變體屬性的默認(rèn)值席怪。
配置產(chǎn)品flavor時(shí)应闯,可以覆蓋任何defaultConfig屬性。
有關(guān)可在此塊中配置的屬性的更多信息挂捻,請(qǐng)參閱ProductFlavor碉纺。
/**
* applicationId uniquely identifies the package for publishing.
* However, your source code should still reference the package name
* defined by the package attribute in the main/AndroidManifest.xml file.
*/
applicationId 'com.example.myapp'
// Defines the minimum API level required to run the app.
minSdkVersion 15
// Specifies the API level used to test the app.
targetSdkVersion 28
// Defines the version number of your app.
versionCode 1
// Defines a user-friendly version name for your app.
versionName "1.0"
..............
在渠道配置這里可以對(duì) config 的屬性進(jìn)行覆蓋 比如這里進(jìn)行的覆蓋就是 appid
productFlavors {
free {
dimension "tier"
applicationId 'com.example.myapp.free'
}
paid {
dimension "tier"
applicationId 'com.example.myapp.paid'
}
}
buildTypes{}
您可以在模塊級(jí) build.gradle
文件的 android
代碼塊內(nèi)部創(chuàng)建和配置構(gòu)建類型。當(dāng)您創(chuàng)建新模塊時(shí)刻撒,Android Studio 會(huì)自動(dòng)為您創(chuàng)建調(diào)試和發(fā)布這兩種構(gòu)建類型骨田。盡管調(diào)試構(gòu)建類型不會(huì)出現(xiàn)在構(gòu)建配置文件中,Android Studio 會(huì)為其配置 debuggable true
疫赎。這樣盛撑,您可以在安全的 Android 設(shè)備上調(diào)試應(yīng)用并使用通用調(diào)試密鑰庫(kù)配置 APK 簽署。
如果您希望添加或更改特定設(shè)置捧搞,您可以將調(diào)試構(gòu)建類型添加到您的配置中抵卫。以下示例為調(diào)試構(gòu)建類型指定了 applicationIdSuffix
狮荔,并配置了一個(gè)使用調(diào)試構(gòu)建類型中的設(shè)置進(jìn)行初始化的“staging”構(gòu)建類型。
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildType 還可以做到對(duì) buildConfig 文件寫入變量來(lái)控制一些字段
在這里設(shè)置的字段 最終會(huì)被編譯到 buildConfig.java中
項(xiàng)目中就可以直接使用 buildConfig 文件來(lái)讀取某些構(gòu)建配置共代碼層使用了介粘。
productFlavors {}
創(chuàng)建產(chǎn)品風(fēng)格與創(chuàng)建構(gòu)建類型相似:只需將其添加到構(gòu)建配置中的 productFlavors
代碼塊并加入所需的設(shè)置即可殖氏。產(chǎn)品風(fēng)格支持與 defaultConfig
相同的屬性,這是因?yàn)?defaultConfig
實(shí)際上屬于 ProductFlavor
類姻采。這意味著雅采,您可以在 defaultConfig
代碼塊中提供所有風(fēng)格的基本配置,每種風(fēng)格均可更改任何這些默認(rèn)值慨亲,例如 applicationId
婚瓜。
// Specifies one flavor dimension.
flavorDimensions "version"
productFlavors {
demo {
// Assigns this product flavor to the "version" flavor dimension.
// This property is optional if you are using only one dimension.
dimension "version"
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}
當(dāng)你配置了產(chǎn)品風(fēng)格以后 buildVariant 會(huì)變成上圖所示的樣子
buildType 與 ProductFlavor 進(jìn)行了交叉組合
他們的區(qū)別是什么呢?
一般情況 buildType 是為了構(gòu)建形式進(jìn)行的設(shè)定刑棵,比如是 debug 還是 release 版本巴刻,這兩種情況有些不同的配置比如服務(wù)器地址或。
productFlavor 更像是針對(duì)構(gòu)建完成后產(chǎn)品的差異而進(jìn)行的配置蛉签,比如我需要構(gòu)建一個(gè) 某平臺(tái)的 apk 包胡陪,這個(gè)平臺(tái)要求的 minsdk 與其他不同 那么我在這里設(shè)置一個(gè)不同的值,兩個(gè)版本的 apk 包碍舍,這時(shí)也可以使用 productFlavor 進(jìn)行設(shè)置柠座,我個(gè)人的理解是 buildType 是配置怎么構(gòu)建,而 productFlavor 是構(gòu)建給誰(shuí)片橡。
splits{}
splits {
// Configures multiple APKs .
...
}
另一個(gè)跟打包相關(guān)的塊是 splits 分包塊
這個(gè)塊里面有兩個(gè)常用的字段
1妈经、abi cpu 架構(gòu)
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "x86_64"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk false
}
}
2、density 屏幕分辨率
splits {
// Configures multiple APKs based on screen density.
density {
// Configures multiple APKs based on screen density.
enable true
// Specifies a list of screen densities Gradle should not create multiple APKs for.
exclude "ldpi", "xxhdpi", "xxxhdpi"
// Specifies a list of compatible screen size settings for the manifest.
compatibleScreens 'small', 'normal', 'large', 'xlarge'
}
}
我們?cè)偌尤?abi 的部分
splits {
// Configures multiple APKs based on screen density.
density {
// Configures multiple APKs based on screen density.
enable true
// Specifies a list of screen densities Gradle should not create multiple APKs for.
exclude "ldpi", "xxhdpi", "xxxhdpi"
// Specifies a list of compatible screen size settings for the manifest.
compatibleScreens 'small', 'normal', 'large', 'xlarge'
}
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "x86_64"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk false
}
}
配置了這些后 如果我們部署測(cè)試機(jī)是怎么樣的锻全?
看到 執(zhí)行了 assembleDemoDebug 也就是 執(zhí)行了 buildTpye debug
productFlavor demo 的組合 而在 build/output/apk中 我們看到了
所以這是先打出所有符合條件的包 再將符合規(guī)則的包部署到測(cè)試機(jī)上狂塘。
除了 splits 對(duì)包進(jìn)行區(qū)分在 productFlavor 也可也達(dá)到同樣的效果
// Specifies one flavor dimension.
flavorDimensions "version","abi"
productFlavors {
arm{
dimension "abi"
ndk {
abiFilters "arm64-v8a", "armeabi", "armeabi-v7a"
}
}
}
這樣在指定 buildVariant 時(shí)就能直接指定 abi 架構(gòu)了
(但是這個(gè)不能與 splits 的 abi 同時(shí)設(shè)置,會(huì)報(bào)沖突錯(cuò)誤)
ERROR: Conflicting configuration : 'armeabi-v7a,armeabi,arm64-v8a' in ndk abiFilters cannot be present when splits abi filters are set : x86_64,x86
Affected Modules: app
sourceSets{}
sourceSets 的配置基本就是指定源文件的路徑,通過(guò)添加一些配置文件的變量鳄厌,可以達(dá)到根據(jù)配置編譯不同的類文件或資源文件荞胡,在模塊化項(xiàng)目中可以做到動(dòng)態(tài)配置 lib木塊功能及界面。