轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/77678577 本文出自 "【趙彥軍的博客】" 其他 "Groovy 使用完全解析 http://blog.csdn.net/zhaoyanjun6/article/details/7 ...
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/77678577
本文出自【趙彥軍的博客】
其他
Groovy 使用完全解析 http://blog.csdn.net/zhaoyanjun6/article/details/70313790
Android Gradle
Android項目使用 Gradle 作為構建框架,Gradle 又是以Groovy為腳本語言。所以學習Gradle之前需要先熟悉Groovy腳本語言。
Groovy是基於Java語言的腳本語言,所以它的語法和Java非常相似,但是具有比java更好的靈活性。下麵就列舉一些和Java的主要區別。
Android Gradle 的 Project 和 Tasks
這個Gradle中最重要的兩個概念。每次構建(build)至少由一個project構成,一個project 由一到多個task構成。項目結構中的每個build.gradle文件代表一個project,在這編譯腳本文件中可以定義一系列的task;task 本質上又是由一組被順序執行的Action`對象構成,Action其實是一段代碼塊,類似於Java中的方法。
Android Gradle 構建生命周期
每次構建的執行本質上執行一系列的Task。某些Task可能依賴其他Task。哪些沒有依賴的Task總會被最先執行,而且每個Task只會被執行一遍。每次構建的依賴關係是在構建的配置階段確定的。每次構建分為3個階段:
- Initialization: 初始化階段
這是創建Project階段,構建工具根據每個build.gradle文件創建出一個Project實例。初始化階段會執行項目根目錄下的settings.gradle文件,來分析哪些項目參與構建。
所以這個文件裡面的內容經常是:
include ':app'
include ':libraries:someProject'
這是告訴Gradle這些項目需要編譯,所以我們引入一些開源的項目的時候,需要在這裡填上對應的項目名稱,來告訴Gradle這些項目需要參與構建。
- Configuration:配置階段
這個階段,通過執行構建腳本來為每個project創建並配置Task。配置階段會去載入所有參與構建的項目的build.gradle文件,會將每個build.gradle文件實例化為一個Gradle的project對象。然後分析project之間的依賴關係,下載依賴文件,分析project下的task之間的依賴關係。
- Execution:執行階段
這是Task真正被執行的階段,Gradle會根據依賴關係決定哪些Task需要被執行,以及執行的先後順序。
task是Gradle中的最小執行單元,我們所有的構建,編譯,打包,debug,test等都是執行了某一個task,一個project可以有多個task,task之間可以互相依賴。例如我有兩個task,taskA和taskB,指定taskA依賴taskB,然後執行taskA,這時會先去執行taskB,taskB執行完畢後在執行taskA。
說到這可能會有疑問,我翻遍了build.gradle也沒看見一個task長啥樣,有一種被欺騙的趕腳!
其實不是,你點擊AndroidStudio右側的一個Gradle按鈕,會打開一個面板,內容差不多是這樣的:
裡面的每一個條目都是一個task,那這些task是哪來的呢?
一個是根目錄下的 build.gradle
中的
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
}
一個是 app 目錄下的 build.gradle
中的
apply plugin: 'com.android.application'
這兩段代碼決定的。也就是說,Gradle提供了一個框架,這個框架有一些運行的機制可以讓你完成編譯,但是至於怎麼編譯是由插件決定的。還好Google已經給我們寫好了Android對應的Gradle工具,我們使用就可以了。
根目錄下的build.gradle中dependencies {classpath 'com.android.tools.build:gradle:2.2.2'}是Android Gradle編譯插件的版本。
app目錄下的build.gradle中的apply plugin: 'com.android.application'是引入了Android的應用構建項目,還有com.android.library和com.android.test用來構建library和測試。
所有Android構建需要執行的task都封裝在工具里,如果你有一些特殊需求的話,也可以自己寫一些task。那麼對於開發一個Android應用來說,最關鍵的部分就是如何來用AndroidGradle的插件了。
認知Gradle Wrapper
Android Studio中預設會使用 Gradle Wrapper 而不是直接使用Gradle。命令也是使用gradlew而不是gradle。這是因為gradle針對特定的開發環境的構建腳本,新的gradle可能不能相容舊版的構建環境。為瞭解決這個問題,使用Gradle Wrapper 來間接使用 gradle。相當於在外邊包裹了一個中間層。對開發者來說,直接使用Gradlew 即可,不需要關心 gradle的版本變化。Gradle Wrapper 會負責下載合適的的gradle版本來構建項目。
Android 三個文件重要的 gradle 文件
Gradle項目有3個重要的文件需要深入理解:項目根目錄的 build.gradle , settings.gradle 和模塊目錄的 build.gradle 。
1.settings.gradle 文件會在構建的 initialization 階段被執行,它用於告訴構建系統哪些模塊需要包含到構建過程中。對於單模塊項目, settings.gradle 文件不是必需的。對於多模塊項目,如果沒有該文件,構建系統就不能知道該用到哪些模塊。
2.項目根目錄的 build.gradle 文件用來配置針對所有模塊的一些屬性。它預設包含2個代碼塊:buildscript{...}和allprojects{...}。前者用於配置構建腳本所用到的代碼庫和依賴關係,後者用於定義所有模塊需要用到的一些公共屬性。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
buildscript:定義了 Android 編譯工具的類路徑。repositories中, jCenter是一個著名的 Maven 倉庫。
allprojects:中定義的屬性會被應用到所有 moudle 中,但是為了保證每個項目的獨立性,我們一般不會在這裡面操作太多共有的東西。
- 3.模塊級配置文件 build.gradle 針對每個moudle 的配置,如果這裡的定義的選項和頂層 build.gradle定義的相同。它有3個重要的代碼塊:plugin,android 和 dependencies。
定製項目屬性(project properties)
在項目根目錄的build.gradle配置文件中,我們可以定製適用於所有模塊的屬性,通過ext 代碼塊來實現。如下所示:
ext {
compileSdkVersion = 22
buildToolsVersion = "22.0.1"
}
然後我們可以在模塊目錄的build.gradle配置文件中引用這些屬性,引用語法為rootProject.ext.{屬性名}。如下:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
Android studio gradle Task
//構建
gradlew app:clean //移除所有的編譯輸出文件,比如apk
gradlew app:build //構建 app module ,構建任務,相當於同時執行了check任務和assemble任務
//檢測
gradlew app:check //執行lint檢測編譯。
//打包
gradlew app:assemble //可以編譯出release包和debug包,可以使用gradlew assembleRelease或者gradlew assembleDebug來單獨編譯一種包
gradlew app:assembleRelease //app module 打 release 包
gradlew app:assembleDebug //app module 打 debug 包
//安裝,卸載
gradlew app:installDebug //安裝 app 的 debug 包到手機上
gradlew app:uninstallDebug //卸載手機上 app 的 debug 包
gradlew app:uninstallRelease //卸載手機上 app 的 release 包
gradlew app:uninstallAll //卸載手機上所有 app 的包
這些都是基本的命令,在實際項目中會根據不同的配置,會對這些task 設置不同的依賴。比如 預設的 assmeble 會依賴 assembleDebug 和assembleRelease,如果直接執行assmeble,最後會編譯debug,和release 的所有版本出來。如果我們只需要編譯debug 版本,我們可以運行assembleDebug。
除此之外還有一些常用的新增的其他命令,比如 install命令,會將編譯後的apk 安裝到連接的設備。
lint 檢測
- 忽略編譯器的 lint 檢查
android {
lintOptions {
abortOnError false
}
}
buildTypes 定義了編譯類型
android{
buildTypes {
release {
minifyEnabled true //打開混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false //關閉混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
productFlavors 多渠道打包
AndroidManifest.xml 里設置動態渠道變數
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
在 build.gradle 設置 productFlavors , 這裡假定我們需要打包的渠道為酷安市場、360、小米、百度、豌豆莢。
android {
productFlavors {
kuan {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "kuan"]
}
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
}
qh360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qh360"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
}
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
}
}
或者批量修改
android {
productFlavors {
kuan {}
xiaomi {}
qh360 {}
baidu {}
wandoujia {}
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
這樣在打包的時候就可以選擇渠道了
或者用命令打包 ,比如:
gradlew assembleWandoujiaRelease //豌豆莢 release 包
gradlew assembleWandoujiaDebug //豌豆莢 debug 包
Signing 簽名
在 android 標簽下添加 signingConfigs 標簽,如下:
android {
signingConfigs {
config {
keyAlias 'yiba'
keyPassword '123456'
storeFile file('C:/work/Key.jks')
storePassword '1234567'
}
}
}
可以在 release 和 debug 包中定義簽名,如下:
android {
signingConfigs {
config {
keyAlias 'yiba'
keyPassword '123456'
storeFile file('C:/work/Key.jks')
storePassword '1234567'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
}
依賴管理
1、依賴 jcenter 包
每個庫名稱包含三個元素:組名:庫名稱:版本號
compile 'com.android.support:appcompat-v7:25.0.0'
2、依賴本地 module
compile project(':YibaAnalytics')
3、依賴 jar 包
- 1、把 jar 包放在 libs 目錄下
- 2、在 build.gradle 中添加依賴
dependencies {
compile files('libs/YibaAnalytics5.jar')
}
4、依賴 aar 包
- 1、把 aar 包放到 libs 目錄下
- 2、在 build.gradle 中添加依賴
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
compile(name:'YibaAnalytics-release', ext:'aar')
}
如圖所示:
5、自定義依賴包目錄
當我們的 aar 包需要被多個 module 依賴時,我們就不能把 aar 包放在單一的 module 中,我們可以在項目的根目錄創建一個目錄,比如叫 aar 目錄,然後把我們的 aar 包放進去,如圖所示:
在項目的根目錄的 build.gradle 的 allprojects 標簽下的 repositories 添加 :
flatDir {
dirs '../aar'
}
../aar
表示根目錄下的 aar 文件夾。
如圖所示:
然後就可以添加依賴了,如下所示:
compile(name:'YibaAnalytics-release', ext:'aar')
6、依賴配置
有些時候,你可能需要和sdk協調工作。為了能順利編譯你的代碼,你需要添加SDK到你的編譯環境。你不需要將sdk包含在你的APK中,因為它早已經存在於設備中,所以配置來啦,我們會有5個不同的配置:
- compile
- apk
- provided
- testCompile
- androidTestCompile
compile是預設的那個,其含義是包含所有的依賴包,即在APK里,compile的依賴會存在。
apk的意思是apk中存在,但是不會加入編譯中,這個貌似用的比較少。
provided的意思是提供編譯支持,但是不會寫入apk。
native包(so包)
用c或者c++寫的library會被叫做so包,Android插件預設情況下支持native包,你需要把.so文件放在對應的文件夾中:
註意
jniLibs 目錄應該和 Java 目錄在同一級
defaultConfig 詳解
defaultConfig 對應的是 ProductFlavor 類。
resConfigs : 過濾語言
如果你的app中僅支持1,2種語言,但是可能引用的lib庫包含多種其他語言的strings資源,這個時候我們可以通過resConfig指定我們需要的strings資源。
android {
defaultConfig {
applicationId "com.yiba.sharewe.lite.activity"
minSdkVersion 14
targetSdkVersion 24
versionCode 46
versionName "1.74"
resConfigs 'en', 'zh-rCN' ,'es' //本次打包,只把 en(英文)、zh-rCN(中文簡體)、es(西班牙語)打進保內,其他語言忽略
}
}
resConfigs : 過濾 drawable文件夾的資源
一般情況下,我們打完包,res 下麵的資源如圖所示:
現在加上資源過濾規則:
android {
defaultConfig {
applicationId "com.wifi.analytics"
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
resConfigs "hdpi" //打包的時候只保留 drawable-xhdpi 文件夾裡面的資源
}
}
這次我們打包效果如下:
buildTypes 詳解
buildTypes{}對應的是 BuildType 類
繼承關係
BuildType 繼承 DefaultBuildType ; DefaultBuildType 繼承 BaseConfigImpl ;
BaseConfigImpl
--- DefaultBuildType
--- BuildType
buildTypes的屬性:
name:build type的名字
applicationIdSuffix:應用id尾碼
versionNameSuffix:版本名稱尾碼
debuggable:是否生成一個debug的apk
minifyEnabled:是否混淆
proguardFiles:混淆文件
signingConfig:簽名配置
manifestPlaceholders:清單占位符
shrinkResources:是否去除未利用的資源,預設false,表示不去除。
zipAlignEnable:是否使用zipalign工具壓縮。
multiDexEnabled:是否拆成多個Dex
multiDexKeepFile:指定文本文件編譯進主Dex文件中
multiDexKeepProguard:指定混淆文件編譯進主Dex文件中
buildType的方法:
1.buildConfigField(type,name,value):添加一個變數生成BuildConfig類。
2.consumeProguardFile(proguardFile):添加一個混淆文件進arr包。
3.consumeProguardFile(proguardFiles):添加混淆文件進arr包。
4.externalNativeBuild(action):配置本地的build選項。
5.initWith:複製這個build類型的所有屬性。
6.proguardFile(proguardFile):添加一個新的混淆配置文件。
7.proguradFiles(files):添加新的混淆文件
8.resValue(type,name,value):添加一個新的生成資源
9.setProguardFiles(proguardFileIterable):設置一個混淆配置文件。
initWith :複製屬性
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.wifi.analytics"
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
myType {
initWith debug //完全複製 debug 的所有屬性‘
minifyEnabled true //自定義打開混淆
}
}
}
applicationIdSuffix 、versionNameSuffix :添加尾碼
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.wifi.analytics"
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationIdSuffix "zhao" //applicationId 追加尾碼名 zhao
versionNameSuffix "debug" //versionName 追加尾碼名 debug1.0
}
}
效果圖,如下:
buildConfigField: 自定義屬性
在 build.gradle 文件中定義 buildConfigField 屬性
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "API_ENV", "\"http://yiba.com\"" //自定義String屬性
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "API_ENV", "\"http://yiba.com\"" //自定義String屬性
}
}
}
然後點擊同步按鈕,然後就可以在 build 目錄看到 debug 和 release 信息。
debug 環境下的 BuildConfig 如下:
release 環境下的 BuildConfig 如下:
當然我們也可以在代碼中獲取自定義的值:
//獲取變數值
String API = BuildConfig.API_ENV ;
上面演示了自定義 String 變數,也可以 自定義 int 、boolean
android {
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "String", "API_ENV", "\"http://www.baidu.com\"" //自定義 String 值
buildConfigField "Boolean", "openLog", "true" //自定義 boolean 值
buildConfigField "int", "age", "10" //自定義 int 值
}
}
}
Gradle 實現差異化構建
情景1
LeakCanary 是 square 公司出品的一個檢測記憶體泄漏的開源庫。
GitHub : https://github.com/square/leakcanary
我們一般這樣集成
dependencies {
compile 'com.squareup.leakcanary:leakcanary-android:1.5.2'
}
然後我們在 Application 類中初始化:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
但是這樣集成有一個弊端,就是 debug 和 release 包都會把 LeakCanary 的源碼打進去,如果我們在 release 包中不把 LeakCanary 源碼打進去,怎麼辦? 還好 LeakCanary 給我們提供了一個方法,方法如下:
dependencies {
//打 debug 包
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
//打 release 包
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
}
leakcanary-android-no-op 是一個空殼,裡面有2個空類,所以就可以避免把 LeakCanary 源碼打進 release 包。但是這種方式有個缺陷,如果一些開源庫沒有提供 releaseCompile 庫,那我們改怎麼辦了?下麵的情景2 就會講到解決方案。
情景2
Stetho 是 Faceboo k開源的Andorid調試工具。當你的應用集成Stetho時,開發者可以訪問Chrome,在Chrome Developer Tools中查看應用佈局,網路請求,sqlite,preference 等等。
官網:http://facebook.github.io/stetho/
從官網可以看到 stetho 沒有提供 releaseCompile 包 , 情景1 的方案就不能用了。新的思路集成方案如下:
dependencies {
debugCompile 'com.facebook.stetho:stetho:1.5.0'
}
在 src 目錄下創建 debug 目錄、release 目錄 ,然後分別在 debug 目錄 和 release 目錄 創建 java 目錄 , 在 java 目錄中創建包名,比如: com.app
, 如下圖所示:
debug 目錄下創建 SDKManage 類 ,如下 :
public class SDKManager {
public static void init(Context context) {
//初始化 Stetho
Stetho.initializeWithDefaults(context);
}
}
release 目錄下創建 SDKManage 類 ,如下 :
public class SDKManager {
public static void init(Context context) {
//這是一個空方法,目的是不引入 Stetho 源碼
}
}
在住項目中的 MyApplication 類,並且完成 Stetho 的初始化,如下:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SDKManager.init(this);
}
}
這樣我們便完成了簡單的差異化構建, 打出來的 release 包就沒有 Stetho 源碼。
SourceSet
SourceSet 簡介
SourceSet 可以定義項目結構,也可以修改項目結構。Java插件預設實現了兩個SourceSet,main 和 test。每個 SourceSet 都提供了一系列的屬性,通過這些屬性,可以定義該 SourceSet 所包含的源文件。比如,java.srcDirs,resources.srcDirs 。Java 插件中定義的其他任務,就根據 main 和 test 的這兩個 SourceSet 的定義來尋找產品代碼和測試代碼等。
SourceSet 定義源碼目錄
在 Android 項目中,我們可以在 src/main/java
目錄新建 Java 文件,如下圖所示:
現在我們在 src 目錄下,新建 test1 目錄 ,發現不能在 test1 目錄中新建 Java 文件,如下圖所示:
為什麼在 test1 目錄不能新建 Java 文件,因為 Gradle 中 SourceSet 預設定義的源碼文件路徑是src/main/java
, 其他的文件下下麵的源碼我們自然無法訪問。解決這個問題也很簡單,我們需要在 SourceSet 中增加一個源碼路徑即可。如下所示:
android {
sourceSets {
main {
java {
srcDir 'src/test1' //指定源碼目錄
}
}
}
}
然後同步一下,就可以在 test1 目錄中新建 Java 文件了。如下圖所示:
當然我們也可以同時指定多個源碼目錄,比如同時指定 test1 , test2 , test3 為源碼目錄。
android {
sourceSets {
main {
java {
srcDir 'src/test1' //指定 test1 為源碼目錄
srcDir 'src/test2' //指定 test2 為源碼目錄
srcDir 'src/test3' //指定 test3 為源碼目錄
}
}
}
}
或者 這樣寫 :
android {
sourceSets {
main {
java.srcDirs( 'src/test1' , 'src/test2' ,'src/test3' )
}
}
}
效果如下圖所示:
SourceSet 定義資源目錄
定義 test1 目錄 Java 源代碼路徑、res 資源目錄。目錄結構如下圖所示:
android {
sourceSets {
main {
java.srcDirs('src/test1/java') //定義java 源代碼
res.srcDirs('src/test1/res') //定義資源目錄(layout , drawable,values)
}
}
}
SourceSet 實現 layout 分包
對於一個大項目來說,頁面太多,佈局文件就很多,有時在眾多佈局文件中找某個模塊的佈局文件,很是痛苦,為瞭解決這個問題,我們可以在創建多個 layout 目錄,不同模塊的佈局文件放在不同的 layout 目錄中,這樣查找起來,就容易很多。
例子:
比如我們的項目中,有兩個模塊分別為:登錄、註冊。
第一步:把項目中 layout 文件夾改名字為 layouts
第二步:在 layouts 目錄下,分別創建 login 、register 目錄 。
第三步:分別在 login 、register 目錄下創建 layout 目錄。註意這一步是必須的,否則會報錯。
第四步:把 登錄佈局文件、註冊佈局文件 分別放在 第三步創建的對應的 layout 目錄下。
效果圖如下:
SourceSet 實現如下:
android {
sourceSets {
main {
res.srcDirs 'src/main/res/layouts/login' //定義登錄佈局目錄
res.srcDirs 'src/main/res/layouts/register' //定義註冊佈局目錄
}
}
}
SourceSet 定義 AndroidManifest 文件
指定 test1 目錄下的 AndroidManifest 文件。項目結構如下圖所示:
代碼如下:
android {
sourceSets {
main {
manifest.srcFile 'src/test1/AndroidManifest.xml'
}
}
}
在組件化開發中, 我們需要針對 debug 與 release 模式下, 指定不同的 Manifest 文件, 代碼如下:
android {
def appDebug = false;
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
appDebug = false;
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
appDebug = false;
}
}
sourceSets {
main {
if (appDebug) {
manifest.srcFile 'src/test1/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
}
}
}
}
SourceSet 定義 assets 目錄
Android Studio 項目目錄中,assets 預設目錄如下:
如何重新定義 assets 目錄 。在項目的根目錄下創建 assets 目錄,如下圖所示:
sourceSets 定義代碼如下:
android {
sourceSets {
main {
assets.srcDirs = ['assets']
}
}
}
SourceSet 定義其他資源
android {
sourceSets {
main {
jniLibs.srcDirs //定義 jni 目錄
aidl.srcDirs //定義 aidl 目錄
}
}
}
applicationVariants
定義 versionName 、VersionCode
在打包的時候分 debug 、release 版本 , 需要控制 versionName
android {
applicationVariants.all { variant ->
def flavor = variant.mergedFlavor
def versionName = flavor.versionName
if (variant.buildType.isDebuggable()) {
versionName += "_debug" //debug 名字
} else {
versionName += "_release" //release 名字
}
flavor.versionName = versionName
}
}
定義 APK 包的名字
apply plugin: 'com.android.application'
android {
defaultConfig {
applicationId "android.plugin"
minSdkVersion 14
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//定義渠道
productFlavors {
xiaomi {
//小米
}
wandoujia {
// 豌豆莢
}
}
//打包命名
applicationVariants.all {
variant ->
variant.outputs.each {
output ->
//定義一個新的apk 名字。
// 新名字 = app 名字+ 渠道號 + 構建類型 + 版本號 + 當前構建時間
def apkName = "appName_${variant.flavorName}_${buildType.name}_v${variant.versionName}_${getTime()}.apk";
output.outputFile = new File(output.outputFile.parent, apkName);
}
}
}
//獲取當前時間
def getTime() {
String today = new Date().format('YY年MM月dd日HH時mm分')
return today
}
效果圖如下:
Task
定義 task
//定義任務1
task task1<<{
println 'task1'
}
//定義任務2
task task2<<{
println 'task2'
}
mustRunAfter 定義 task 執行順序
//task2 的執行順訊在 task1 之後
task2.mustRunAfter task1
- 測試1 : gradlew task1
效果如下:
:app:task1
task1
- 測試2 : gradlew task2
效果如下:
:app:task2
task2
- 測試3 : gradlew task1 task2
效果如下:
:app:task1
task1
:app:task2
task2
- 測試4 : gradlew task2 task1
效果如下:
:app:task1
task1
:app:task2
task2
結論
如果單獨執行 task1 就只會執行 task1 的任務;單獨執行 task2 就只會執行 task2 的任務;
如果同時執行 task1、task2 , 一定會先執行 task1 , 等 task1 執行完後,就會執行 task2 內容。
擴展
上面 mustRunAfter 我們還有一種寫法,如下圖所示:
task2 {}.mustRunAfter task1
這個寫法的效果和 mustRunAfter 是一樣的,當然我們還可以在 花括弧裡面寫一些任務,比如 :
task2 {
println '我最先執行'
}.mustRunAfter task1
下麵做個測試,測試命令如下:
gradlew task2 task1
效果如下:
我最先執行
:app:task1
task1
:app:task2
task2
dependsOn 定義 task 依賴
task2 任務依賴於 task1 ,執行 task2 就會先執行 task1
task2.dependsOn task1
測試:
gradlew task2
效果如下:
:app:task1
task1
:app:task2
task2
常用 Gradlew 命令
- 1、gradlew -v : 查看版本號
------------------------------------------------------------
Gradle 3.3
------------------------------------------------------------
Build time: 2017-01-03 15:31:04 UTC
Revision: 075893a3d0798c0c1f322899b41ceca82e4e134b
Groovy: 2.4.7
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_112 (Oracle Corporation 25.112-b15)
OS: Windows 10 10.0 amd64
- 2、gradlew task : 查看所有的 task
參考資料
個人微信號:zhaoyanjun125
, 歡迎關註