Gradle簡介
Gradle是一個自動化構建工具,采用Groovy的Domain Specific Language(領域特定語言)來描述和控制構建邏輯。具有語法簡潔、可讀性強、配置靈活等特點。基於Intellij IDEA社區版本開發的Android Studio天生支持Gradle構建程序。Groovy是一種基於JVM的敏捷開發語言,結合了Phthon、Ruby和Smalltalk的許多強大特性。同時,Groovy代碼既能夠與java代碼很好地結合,也能夠用於擴展現有的代碼。
Gradle有如下特點:
- Gradle支持多工程構建和局部構建
- Gradle支持遠程或本地依賴管理:支持從遠程maven倉庫(項目構建工具、軟件項目管理綜合工具)、nexus私服(局域網內一種特殊的遠程倉庫)、ivy倉庫(管理項目依賴的工具)以及本地倉庫獲取依賴
- Gradle與Ant、Maven兼容
- Gradle可輕松遷移:Gradle適用於任何結構的工程,可以在同一個開發平台平行構建原工程和Gradle工程
- Gradle使用靈活:Gradle的整體設計是以作為一種語言為導向的,而非成為一個嚴格死板的框架
- Gradle免費開源
- Gradle很好的與IDE集成
- Gradle可以更容易地集成到自動化構建系統
Android Studio下項目構建的Gradle配置
在Android Studio下創建一個Android項目,並切換到Project視圖下,可以看到下圖的項目結構。
紅框標記就是項目中Gradle相關的配置文件,下面我們從app模塊下的build.gradle開始對各個配置文件進行分析。
一、app Module下的build.gradle文件說明
app這個Module下的gradle配置文件,算是整個項目最主要的gradle配置文件,主要配置應用程序屬性、配置應用程序簽名、配置應用程序特性(渠道)、配置應用程序構建類型和配置應用程序依賴,下圖是默認生成的文件內容:
1. 應用插件apply plugin總共有三種類型值,分別如下:
apply plugin:
‘com.android.application’//這表示此module是一個可運行的應用程序,可以直接run的
apply plugin: ‘com.android.library’//這表示此module是一個安卓依賴庫的工程,不可直接run
apply plugin: ‘java’//這表示此module是一個java項目,在此module中只能使用java的api
2. 關於android閉包,
其默認有compileSdkVersion、buildToolsVersion、defaultConfig閉包和buildTypes閉包。
compileSdkVersion和buildToolsVersion是兩個關於版本描述的參數
compileSdkVersion 25//指定編譯版本,開發采用的sdk版本
buildToolsVersion “25.0.2”//編譯時采用的構建工具的版本
defaultConfig閉包參數說明
applicationId “com.jointem.variantpackaging”//應用的id,這里決定應用的唯一標識
minSdkVersion 17//決定此應用可運行的安卓系統最低版本
targetSdkVersion 25//決定此應用可運行的安卓系統最高版本
versionCode 1//應用版本號,更新需要,新包的值要大於老包的方可更新
versionName ‘1.0’//應用版本名,通常用於顯示
testInstrumentationRunner”andrid.support.test.runner.AndroidJUnitRunner”//Android單元測試test runner
buildTypes閉包參數說明
關於構建類型buildType,默認有release和debug兩種,默認只顯示release方式,一般是正式發布的包。
minifyEnabled false//混淆開關
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’// 指定混淆文件及混淆文件規則配置文件的位置
3.關於模塊依賴dependencies
compile fileTree(include: [‘*.jar’], dir: ‘libs’)//編譯文件樹(編譯依賴libs目錄下所有jar)
androidTestCompile(‘com.android.support.test.espresso:espresso-core:2.2.2’, {
exclude group: ‘com.android.support’, module: ‘support-annotations’
})
compile ‘com.android.support:appcompat-v7:24.2.1’//是從repository(默認是jCenter())里下載一個依賴包進行編譯並打包
compile ‘com.android.support.constraint:constraint-layout:1.0.0-beta5’
testCompile ‘junit:junit:4.12’// 僅僅是針對單元測試代碼的編譯編譯以及最終打包測試apk時有效,而對正常的debug或者release apk包不起作用
compile project(‘:andr-library’)//是將另一個module進行編譯並打包
其實,app下的腳本對應的是項目的Project Structure對話框中的設置,從左到右依次是屬性、簽名、渠道特性、構建類型和依賴,快捷鍵Ctrl+Shift+Alt+S(Windows/Linux),如下。
二、library Module下的build.gradle配置
除了app Module,每一個Module也都有一個gradle配置文件,語法都一樣,區別在於開頭聲明的是apply plugin: ‘com.android.library’,表明該Module是以依賴模塊的形式存在。
三、全局配置文件
所有的全局配置文件都會放置在項目的根目錄下,包括忽略文件、本地配置文件、gradlew的批處理文件以及項目gradle相關的配置文件。
1.gradle配置文件gradle-wrapper.properties,默認內容如下:
#Thu Mar 09 16:27:37 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
此配置文件中主要聲明了gradle的目錄與下載路徑以及當前項目使用的gradle版本,這些默認的路徑我們一般不會更改的,這個文件里指明的gradle版本不對也是很多導包不成功的原因之一。
2.關於project下build.gradle配置文件
整個項目的gradle基礎配置文件,用來配置項目的構建任務,內容如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules.// 項目構建文件,可以在各子項目/模塊添加常用的配置選項。
buildscript {
//Android插件從這個倉庫下載
repositories {
jcenter()//依賴倉庫源的名稱,兼容maven的遠程中央倉庫
}
//項目依賴
dependencies {
//android gradle插件
classpath 'com.android.tools.build:gradle:2.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
//此處配置Project中默認的倉庫源,包括每個module的依賴,無需每個module單獨配置
repositories {
jcenter()
}
} //打包前執行clean任務 //任務類型是Delete //clean任務就是刪除項目根目錄下的build目錄中的文件
task clean(type: Delete) {
delete rootProject.buildDir
}
3.關於Gradle配置文件gradle.properties
gradle.properties是Gradle的配置文件,build.gradle通過讀取這個文件配置的參數來進行相應構建,可在此配置文件中配置一些全局參數(全局代理)。默認文件內容如下:
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# 配置守護進程的jvm參數
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
#配置完成后,Gradle將在並行模式下運行(並行編譯)
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
#http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
4.關於全局配置文件setting.gradle
默認文件內容include ‘:app’。是項目的全局配置文件,主要聲明一些需要加入構建的模塊。在Android studio中通常都是默認自動在此文件中添加依賴的module。
Android Studio下的依賴方式
一、Project Structure
按快捷鍵Ctrl+Shift+Alt+S(Windows/Linux),打開Project Structure彈窗。
在Dependencies下有個scope,這里可以選擇依賴的方式,可選項有Compile、Provided、APK、Test compile、Debug compile和Release compile,下面分別對這些可選項進行簡單說明。
- Compile:是對所有的build type以及favlors都會參與編譯並且打包到最終的apk文件中,是從repository(默認是jCenter())里下載一個依賴包進行編譯並打包。
- Provided:Provided是對所有的build type以及favlors只在編譯時使用,類似eclipse中的external-libs,只參與編譯,不打包到最終apk,是提供給那些只編譯不打包場景的命令。就是我在編譯的時候對某一個jar文件有依賴,但是最終打包apk文件時,我不想把這個jar文件放進去,可以用這個命令。
- APK:只會打包到apk文件中,而不參與編譯,所以不能再代碼中直接調用jar中的類或方法,否則在編譯時會報錯。
- Test compile:僅僅是針對單元測試代碼的編譯編譯以及最終打包測試apk時有效,而對正常的debug或者release apk包不起作用。
- Debug compile:僅僅針對debug模式的編譯和最終的debug apk打包。
- Release compile:僅僅針對Release 模式的編譯和最終的Release apk打包。
二、關於Compile的兩個子參數:
- compile files:是從本地的libs目錄下尋找picasso-2.4.0.jar這個文件進行編譯並打包。類似的命令有
compile fileTree(dir: 'libs', include: '*.jar')
,即,將libs目錄下所有jar文件進行編譯並打包。 - compile project:是將另一個module(等同eclipse中的library)進行編譯並打包。
打出多變體包
一、為什么要打包變體包?
在開發過程中經常遇到多個環境切換的問題,比如,正在連接測試環境進行調試,此時又想看生產環境的數據顯示,通常的處理方式是卸掉測試環境的然后運行一個生產環境的包。我們都知道,build一個大項目,直到安裝到手機上,整個過程是很耗時的。如果同一台手機上可以同時安裝同一個應用的多個不同環境的apk,那么,當想看其它環境的數據時,就不需要重新卸載再安裝了(同理,同一應用,需要不同版本的安裝包[免費版/收費版]時,也可以這樣處理,而無需為不同版本創建不同的分支)。
二、打包變體包的條件
在創建完一個項目后,我們在app這個module下的build.gradle中的android節點下defaultConfig節點中,可以看到一個applicationId屬性,默認的 applicationId 和 AndroidManifest.xml 中的 package 屬性是相同的。applicationId 和 packageName 它們各自代表什么?為何會是相同的呢?其實,package 代表了 java 代碼中的包名,在應用中的資源,就是通過package標識的(比如R文件,包名.R);applicationId 則代表了應用中的唯一標識,和應用簽名一起用來區別於其他應用。
在手機上,系統同樣是通過applicationId和簽名來標識一個app的。所以,我們只要在打包apk時,使得應用之間的applicationId和簽名各不相同,就能夠實現同一個應用的不同變體同時安裝在同一台手機上了。同時,為了更好的區分給個變體應用,我們還可以通過對占位符的使用,使用gradle配置不同的資源文件、不同的應用名稱與圖標、不同的java文件等有區別的屬性,打出不同的變體包。
三、打出變體包的步驟
1.配置簽名、渠道(applicationId)
選擇app module,選擇Signing選項卡,首先配置好了這兩個變體版本的簽名文件,文件名可任意取(見名知意)。
簽名屬性字段描述:
- keyAlias//指定簽名文件的別名
- keyPassword//指定簽名文件的別名配對密碼
- storeFile//簽名文件路徑
- storePassword//簽名文件的密碼
切換到Flavors選項卡,配置變體包的相關屬性,由於下一步創建資源文件夾時,需要與這里的文件名對應,所以此處的取名盡量簡約。這里我創建兩個命名dev和rea的Flavor,所有的Flavor都會復寫defaultConfig中的屬性,所以可以看到我並沒有填寫其中的一些屬性。在這里非常關鍵的一點,是對不同的變體設置不同的applicationId,並選擇對應的Signing Config。
2.新建不同變體的sourceSet
在修改完變體的配置文件后,我們還需要再項目的src文件夾下,新建以我們的Flavor名稱命名的文件夾,並在這些文件夾下新建如main中相同的目錄結構。
我們正常編寫項目都是寫在main這個sourceSet下的,但是如果我們的項目的變體有不同的資源文件、Java文件時,我們就需要使用不同的sourceSet來區別開。
需要注意的是,Flavor下的資源文件會與main中的合並,如果存在重復,則Flavor中優先級高於main中。我們可以將不同變體中共用的資源存放在main中,只將不同的內容存放在flavor的sourceSet中。
如果不同變體有內容不同的Java文件則要注意,需要將這個Java文件放置到每個flavor 的sourceSet文件夾下,main中不可以有這個Java文件,如果main中也存在此文件,編譯時會提示文件重復。比如說有兩個變體,有着不同的TargetActivity.java,那么main中就不能有這個文件了,需要把這個Java文件放到各個flavor的sourceSet下,同時這個Java文件在sourceSet中要按照main中的包結構保存。
3.關於配置不同的launcher圖標和應用名
通過之前的操作,已經可以有效區分變體包的applicationId、Signing Config和java文件,那么應用logo和name又該如何處理呢,這里有兩種方法。
1)配置不同的資源:我們可以使用類似於處理java文件的方法,在不同的sourceSet中配置string.xml中app_name屬性,在mipmap文件夾中放置對應的ic_app.png圖標資源。不過當我們需要更換啟動圖和應用名而變體包又比較多的情況下,這種方法會比較麻煩,因為我們要到每一個sourceSet資源文件下去對應的修改,如果使用占位符的方式,那么會變得簡單一些。
2)使用占位符的方式:在AndroidManifest文件中使用占位符然后在flavor中直接配置,在flavor中使用的屬性是manifestPlaceholderss(manifestPlaceholders =[NAME1:VALUE1]),而圖標資源和應用名稱我們都可以直接放置到main中。
結果如下圖:
四、Debug時選擇變體
1.選擇要調試的應用
通過之前的操作,已經成功配置了多個變體,那么問題來了,這么多個變體,我們在debug的時候,我們怎么選擇要debug的變體呢?這里有兩種方式進行切換。
- 選擇Build->Select Build Variant,在左下角會顯示出Build Variant視圖,點擊選擇要編譯的變體。
- 另一種方式則是直接點擊左下角Build Variant選下卡,之后的操作同上。
2.需要注意的的地方
- 在這里可以看到有4個變體,這是為什么呢?我們明明只配置了兩個變體呀?在這需要提到Build Type配置,這個選項卡下默認有兩個類型,分別是debug和release,變體包的數量正是(build type數量)*(flavor數量)。
- 當你選擇完要編譯的變體后,會發現未被選中的變體下會報找不到資源的錯誤,這是很正常的,當被選中之后就會變成正常的工程文件夾樣式了,其這種報錯也並不會影響我們進行批量打包。
五、常用gradlew命令
首次運行命令行,沒有gradle的要下載的哦,下載需要的時間根據網絡狀況而定。
1.八個常用命令:
- ./gradlew -v //查看gradle版本
- ./gradlew assembleDebug //編譯並打出Debug版本的包
- ./gradlew assembleRelease //編譯並打出Release版本的包
- ./gradlew build //執行檢查並編譯打包,打出所有Release和Debug的包
- ./gradlew clean //刪除build目錄,會把app下面的build目錄刪掉
- ./gradlew installDebug //編譯打包並安裝Debug版本的包
- ./gradlew uninstallDebug //卸載Debug版本的包
- ./gradlew -info //使用-info查看任務詳情
2.命令行終端Terminal下執行打包命令
我們直接利用./gradlew build打出所有的變體包,在Terminal終端下鍵入./gradlew build命令,需要等待大概20秒鍾左右,當看到終端打印出BUILD SUCCESSFUL,說明打包任務執行完成,打開指定的apk生成目錄(默認app/build/outputs/apk),就可以看到已經打出的apk。
將兩個release包都安裝到同一台手機,可以發現能同時存在,並且都能正常打開運行。
3.關於打包需要注意的坑
如果項目中存在使用Library Module,並且Library Module中manifest下的application也存在與app Module下的application相同的屬性標簽,那么會報manifest.xml合並錯誤的提示,如下。
- 原因:這是因為AS的Gradle插件默認會啟用Manifest Merger Tool,若Library項目中也定義了與主項目相同的屬性(例如默認生成的android:icon和android:theme),則此時會合並失敗,並報上面的錯誤。
- 處理辦法:在Manifest.xml的application標簽下添加tools:replace=”android:icon, android:theme”(多個屬性用,隔開,並且記住在manifest根標簽上加入xmlns:tools=”http://schemas.android.com/tools”,否則會找不到namespace哦)。
注:本篇博客純屬個人筆記,如果錯誤之處,還望幫忙指正,謝謝!
本文固定鏈接: CPP學習網_CPP大學- Android Studio下項目構建的Gradle配置及打包應用變體