前言
- Android Gradle
- 多渠道打包
- Walle錯誤匯總
1、Android Gradle
1.1、Gradle概述
Gradle是基于Groovy語言定義的一套DSL,所謂DSL(領(lǐng)域?qū)S谜Z言),就是專門針對某一特定問題的計算機語言。而Gradle我們可以認為是經(jīng)過“定制”的Groovy,專門用于項目構(gòu)建的語言。
1.2、Groovy概述
Groovy 是一種動態(tài)語言。這種語言比較有特點,它和 Java 一樣,也運行于 Java 虛擬機中。簡單來說,Groovy 是在 java 平臺上的、 具有像 Python, Ruby 和 Smalltalk 語言特性的靈活動態(tài)語言, Groovy 保證了這些特性像 Java 語法一樣被 Java 開發(fā)者使用。
因為Groovy是一門語言,所以完整的學(xué)習(xí)起來不會比學(xué)任一語言要簡單。但是作為一名普通的Android開發(fā)者,其實只要掌握其基礎(chǔ)語法以及它特殊的一點—Closure(閉包),足矣。
推薦閱讀: Gradle從入門到實戰(zhàn) - Groovy基礎(chǔ) | 官方文檔
1.3、Gradle構(gòu)成
Gradle里面有三個重要的概念:Project、Task和Plugin。
- Project
每個項目的編譯至少有一個 Project,一個build.gradle就代表一個project,在Gradle中,每一個project,Gradle都會創(chuàng)建一個Project對象,并將這個對象與構(gòu)建腳本相關(guān)聯(lián)。也就是說,Project對象與build.gradle是一對一的關(guān)系,所以你在build.gradle寫的每一個配置其實就是它對應(yīng)的Project對象的一個方法或者一個變量值,譬如說我們配置項目依賴:
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
}
它其實對應(yīng)Project對象void dependencies(Closure configureClosure);方法。
- Task
Task表示一些需要執(zhí)行的構(gòu)建任務(wù),定義一個Task可以這樣寫:
task hello << {
println "hello"
}
//或者等價于完整的寫法
task("hello").leftShift({
println "hello"
})
- 定義一個task相當(dāng)于調(diào)用了Project對象的task方法
- 任務(wù)名是task方法的參數(shù)名
-
<<是Groovy的運算符重載,在Groovy中,其實就是leftShift方法,leftShift方法 等價于doLast,doLast是gradle提供訪問task任務(wù)的一個API,類似的還有doFirst,當(dāng)一個task被執(zhí)行的時候,可以通過doFirst和doLast向task中動態(tài)添加操作。doFirst/doLast會在task本身被執(zhí)行之前/之后才會被執(zhí)行 -
leftShift方法接收的參數(shù)是一個Closure
簡單來說:一個Task其實就是一個標(biāo)準的Groovy函數(shù)調(diào)用
- Plugin
Gradle是一個框架,作為框架,它負責(zé)定義流程和規(guī)則。而具體的編譯工作則是通過插件的方式來完成的。比如編譯Java有Java插件,編譯Groovy有Groovy插件,編譯Android APP有Android APP插件,編譯Android Library有Android Library插件。簡單來說,插件就是一系列任務(wù)的集合,主要作用是把一些重復(fù)利用的邏輯打包,這樣就可以在不同的項目中可以重復(fù)的使用。要應(yīng)用插件,可以通過引入依賴的方式添加,舉個例子,要引入Android APP插件,就需要在build.gradle引用Android APP插件:
buildscript {
repositories {
jcenter()//表示編譯過程中依賴的倉庫
}
dependencies {
//依賴android開發(fā)的gradle插件,groupId:artifactId:version
classpath 'com.android.tools.build:gradle:1.5.0'
}
}
//應(yīng)用插件
apply plugin: 'com.android.application'
//配置插件屬性
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.test"
versionCode 1
versionName "1.0.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
1.4、Gradle編譯周期
- 初始化階段
創(chuàng)建 Project 對象,如果有多個build.gradle,也會創(chuàng)建多個project。 - 配置階段
在這個階段,會執(zhí)行所有的編譯腳本,同時還會創(chuàng)建project的所有的task,為后一個階段做準備。 - 執(zhí)行階段
在這個階段,Gradle 會根據(jù)傳入的參數(shù)決定如何執(zhí)行這些task,真正的執(zhí)行代碼就在這里。
關(guān)于Gradle,更多的學(xué)習(xí)推薦閱讀:Gradle完整指南 | 深入理解 Android(一):Gradle 詳解 | 抓重點學(xué)Gradle
2、多渠道打包
在我的Mentor給我分配我們項目打包需求的時候,一度很迷惑,多渠道打包的意義在哪里,除開一些與廠商定制版的APP,完全不知道為什么要打那么多的渠道包(我們的項目里面甚至要打到3位數(shù)的不同的apk包),后來在慢慢的摸索中,大概是了解到了一點多渠道打包的眉目。
2.1、什么是多渠道打包
渠道包就是要在安裝包中添加渠道信息,也就是channel,對應(yīng)不同的渠道,例如:小米市場、360市場、華為市場、應(yīng)用寶市場等。產(chǎn)品在不同的應(yīng)用市場可能有不同的統(tǒng)計需求,需要為每個應(yīng)用市場的Android包設(shè)定一個可以區(qū)分應(yīng)用市場的標(biāo)識,這個為Android包設(shè)定應(yīng)用市場標(biāo)識的過程就是多渠道打包。
2.2、為什么要多渠道打包
國內(nèi)存在著有眾多的應(yīng)用市場,產(chǎn)品在不同的渠道可能有不同的統(tǒng)計需求,為此Android開發(fā)人員需要為每個應(yīng)用市場發(fā)布一個安裝包,這里就引出了Android的多渠道打包。在安裝包中添加不同的標(biāo)識,應(yīng)用在請求網(wǎng)絡(luò)的時候攜帶渠道信息,方便后臺做運營統(tǒng)計。
2.3、實現(xiàn)多渠道打包
因為目前Android的簽名方式采用的是v2,所以之前使用v1簽名的打包方式就被判了“死刑”。這里推薦現(xiàn)在比較主流的兩種打包:美團Walle和Gradle productFlavors。
推薦閱讀: 美團Walle | Gradle中productFlavors使用詳解
3、Walle的錯誤匯總
在這一周為我們的項目集成Walle時,其實踩了不少的坑,雖然項目代碼不能具體的公開,但是踩過的坑還是可以分享出來的。
踩坑1:ERROR: A problem occurred configuring project ':app'.
產(chǎn)生原因:在buildTypes中沒有配置我們剛剛創(chuàng)建的簽名信息。
解決方法: 在buildTypes中添加我們的簽名信息:

在這里需要注意,我們在配置signingConfig signingConfigs.xxx時,xxx必須和我們之前創(chuàng)建的簽名信息的名字以及buildTypes中的名稱對應(yīng),如果配置了多個簽名信息則需要創(chuàng)建多個小閉包:

踩坑2:Could not initialize class org.codehaus.groovy.runtime.InvokerHelper
產(chǎn)生原因: 是由于jdk版本和gradle版本不匹配。在使用Oracle JDK 14時,所有g(shù)radle(6.2.2)任務(wù)都會失敗。
解決方法: 降低jdk版本或者提高gradle版本到6.3及以上。
踩坑3:Task 'assembleReleaseChannels' not found in root project XXXProject ''.
產(chǎn)生原因: 項目之前的打包方式是采用productFlavors進行多渠道打包。
錯誤解決方法: 在網(wǎng)上查看相關(guān)blog,說是直接將productFlavors中相關(guān)配置直接注釋掉即可,但是經(jīng)過實測,光注釋掉productFlavors相關(guān)配置只是治標(biāo)不治本,后續(xù)產(chǎn)生的錯誤會更多。
正確解決方法: 查看Walle倉庫的issue,發(fā)現(xiàn)Walle本身是支持在配置productFlavors時一鍵生成多個渠道包,所以根本原因并不是productFlavors。解決方法描述如下:
可以檢查有沒有配置
productFlavors,如果有,需要在assemble{$flavor.name}ReleaseChannels.另外還可以在AndroidStudio,Gradle->Project->{your app module name} -> package下面找到你可以使用的命令集合。
