個人博客原文地址html
Gradle是一種構建工具,它拋棄了基於XML的構建腳本,取而代之的是採用一種基於Groovy的內部領域特定語言(DSL),建議能夠先熟悉一下Groovy腳本。
Gradle API 文檔
Android 配置構建
Android 插件 DSL 擴展
本文只是簡單的介紹一下 Gradle 的一些基本配置,若是想進行一些高級的操做或者是想深刻的瞭解這些配置,請參考個人後面幾篇博客。
Gradle 使用指南 – Android DSL 擴展
Gradle 使用指南 – Gradle Task
Gradle 使用指南 – 建立Plugin
Gradle 使用指南 – Plugin DSL 擴展java
gradle明明通常是./gradlew +參數
, gradlew
表明 gradle wrapper
,意思是gradle的一層包裝,你們能夠理解爲在這個項目本地就封裝了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties
文件中聲明瞭它指向的目錄和版本。只要下載成功便可用grdlew wrapper
的命令代替全局的gradle
命令。react
./gradlew -v
版本號./gradlew clean
清除app目錄下的build文件夾./gradlew build
檢查依賴並編譯打包./gradlew tasks
列出全部task這裏注意的是 ./gradlew build
命令把debug、release環境的包都打出來,若是正式發佈只須要打Release的包,該怎麼辦呢,下面介紹一個頗有用的命令 assemble
, 如:android
./gradlew assembleDebug
編譯並打Debug包./gradlew assembleRelease
編譯並打Release的包除此以外,assemble
還能夠和productFlavors
結合使用:git
./gradlew installRelease
Release模式打包並安裝./gradlew uninstallRelease
卸載Release模式包好比咱們想根據不一樣的參數來進行不用的編譯配置,能夠在./gradlew
中加入自定義參數。github
./gradlew assembleDebug -Pcustom=true
就能夠在build.gradle
中使用下面代碼來判斷:segmentfault
if (project.hasProperty('custom')){ }
assemble
還能和 Product Flavor
結合建立新的任務,其實 assemble
是和 Build Variants
一塊兒結合使用的,而 Build Variants = Build Type + Product Flavor
,舉個例子你們就明白了:
若是咱們想打包 wandoujia 渠道的release
版本,執行以下命令就行了:api
./gradlew assembleWandoujiaRelease
若是咱們只打wandoujia渠道版本,則:架構
./gradlew assembleWandoujia
此命令會生成wandoujia渠道的Release和Debug版本
同理我想打所有Release版本:app
./gradlew assembleRelease
這條命令會把Product Flavor下的全部渠道的Release版本都打出來。
總之,assemble
命令建立task有以下用法:
assemble<Variant Name>
: 容許直接構建一個Variant版本,例如assembleFlavor1Debug
。assemble<Build Type Name>
: 容許構建指定Build Type的全部APK,例如assembleDebug
將會構建Flavor1Debug和Flavor2Debug兩個Variant版本。assemble<Product Flavor Name>
: 容許構建指定flavor的全部APK,例如assembleFlavor1
將會構建Flavor1Debug和Flavor1Release兩個Variant版本。Gradle構建腳本 build.gradle
Gradle屬性文件 gradle.properties
Gradle設置文件 settings.gradle
先看整個項目的gradle配置文件:
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.3.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } }
內容主要包含了兩個方面:一個是聲明倉庫的源,這裏能夠看到是指明的jcenter()
, 以前版本則是mavenCentral()
, jcenter
能夠理解成是一個新的中央遠程倉庫,兼容maven
中心倉庫,並且性能更優。
另外一個是聲明瞭android gradle plugin的版本,android studio 1.0正式版必需要求支持gradle plugin 1.0的版本
某個Moudle的gradle配置文件:
buildscript { repositories { maven { url 'http://*********' } } dependencies { classpath 'com.android.tools.build:gradle:1.3.1' } }
buildscript{}
設置腳本的運行環境。repositories{}
支持java依賴庫管理,用於項目依賴。dependencies{}
依賴包的定義。支持maven/ivy
,遠程,本地庫,也支持單文件。若是前面定義了repositories{}
maven 庫,則使用maven的依賴庫,使用時只須要按照用相似於com.android.tools.build:gradle:0.4
,gradle 就會自動的往遠程庫下載相應的依賴。//聲明引用 com.android.application 插件,那麼這個模塊就是一個Android應用程序 apply plugin: 'com.android.application'
apply plugin
:聲明引用插件的類型。若是是庫的話就加apply plugin: 'com.android.library'
apply from
:表示引用其餘的配置文件,好比 apply from:"config.gradle"
這個是 Android 插件引入的 Script blocks,想深刻了解的話看我後面的博客。
android { // 編譯SDK的版本 compileSdkVersion 22 // build tools的版本 buildToolsVersion "23.0.1" //aapt配置 aaptOptions { //不用壓縮的文件 noCompress 'pak', 'dat', 'bin', 'notice' //打包時候要忽略的文件 ignoreAssetsPattern "!.svn:!.git" //分包 multiDexEnabled true //--extra-packages是爲資源文件設置別名:意思是經過該應用包名+R,com.android.test1.R和com.android.test2.R均可以訪問到資源 additionalParameters '--extra-packages', 'com.android.test1','--extra-packages','com.android.test2' } //默認配置 defaultConfig { //應用的包名 applicationId "com.example.heqiang.androiddemo" minSdkVersion 21 targetSdkVersion 22 versionCode 1 versionName "1.0" } //編譯配置 compileOptions { // java版本 sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } //源文件目錄設置 sourceSets { main { //jni lib的位置 jniLibs.srcDirs = jniLibs.srcDirs << 'src/jniLibs' //定義多個資源文件夾,這種狀況下,兩個資源文件夾具備相同優先級,即若是一個資源在兩個文件夾都聲明瞭,合併會報錯。 res.srcDirs = ['src/main/res', 'src/main/res2'] //指定多個源文件目錄 java.srcDirs = ['src/main/java', 'src/main/aidl'] } } //簽名配置 signingConfigs { debug { keyAlias 'androiddebugkey' keyPassword 'android' storeFile file('keystore/debug.keystore') storePassword 'android' } } buildTypes { //release版本配置 release { debuggable false // 是否進行混淆 minifyEnabled true //去除沒有用到的資源文件,要求minifyEnabled爲true才生效 shrinkResources true // 混淆文件的位置 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' signingConfig signingConfigs.debug //ndk的一些相關配置,也能夠放到defaultConfig裏面。 //指定要ndk須要兼容的架構(這樣其餘依賴包裏mips,x86,arm-v8之類的so會被過濾掉) ndk { abiFilter "armeabi" } } //debug版本配置 debug { debuggable true // 是否進行混淆 minifyEnabled false //去除沒有用到的資源文件,要求minifyEnabled爲true才生效 shrinkResources true // 混淆文件的位置 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' signingConfig signingConfigs.debug //ndk的一些相關配置,也能夠放到defaultConfig裏面。 //指定要ndk須要兼容的架構(這樣其餘依賴包裏mips,x86,arm-v8之類的so會被過濾掉) ndk { abiFilter "armeabi" } } } // lint配置 lintOptions { //移除lint檢查的error abortOnError false //禁止掉某些lint檢查 disable 'NewApi' } }
android{}
設置編譯android項目的參數,構建android項目的全部配置都寫在這裏。
除了上面寫的,在android{}
塊中能夠包含如下直接配置項:
productFlavors{ }
產品風格配置,ProductFlavor類型testOptions{ }
測試配置,TestOptions類型dexOptions{ }
dex配置,DexOptions類型packagingOptions{ }
PackagingOptions類型jacoco{ }
JacocoExtension類型。 用於設定 jacoco版本splits{ }
Splits類型。幾點說明:
apply plugin
是最新gradle版本的寫法,之前的寫法是apply plugin: 'android'
, 若是仍是之前的寫法,請改正過來。minifyEnabled
也是最新的語法,很早以前是runProguard
,這個也須要更新下。proguardFiles
這部分有兩段,前一部分表明系統默認的android程序的混淆文件,該文件已經包含了基本的混淆聲明,免去了咱們不少事,這個文件的目錄在 sdk目錄/tools/proguard/proguard-android.txt
, 後一部分是咱們項目裏的自定義的混淆文件,目錄就在 app/proguard-rules.txt
, 若是你用Studio 1.0建立的新項目默認生成的文件名是 proguard-rules.pro
, 這個名字不要緊,在這個文件裏你能夠聲明一些第三方依賴的一些混淆規則。最終混淆的結果是這兩部分文件共同做用的。aaptOptions
更多介紹 http://blog.csdn.net/heqiangflytosky/article/details/51009123好比在gradle的某個地方想使用版本號,可使用下面的方法:
def getVersionCode() { int code = android.defaultConfig.versionCode return code }
repositories { flatDir { //本地jar依賴包路徑 dirs '../../../../main/libs' } }
dependencies { compile files('libs/android-support-v4.jar') //在flatDir.dirs下面找依賴的aar compile (name:'ui', ext:'aar') // 編譯extras目錄下的ShimmerAndroid模塊 // 使用transitive屬性設置爲false來排除全部的傳遞依賴,默認爲true compile project(':extras:ShimmerAndroid'){ transitive = false } // 編譯CommonSDK模塊,可是去掉此模塊中對com.android.support的依賴,防止重複依賴報錯 compile (project(':CommonSDK')) { exclude group: "com.android.support" } provided fileTree(dir: 'src/android5/libs', include: ['*.jar']) provided 'com.android.support:support-v4:21.0.3' provided project(':main-host') //通用使用exclude排除support-compat模塊的依賴 compile ('com.jakewharton:butterknife:8.5.1'){ exclude module: 'support-compat' } }
compile
和provided
compile
表示編譯時提供並打包進apk。 provided
表示只在編譯時提供,不打包進apk。exclude
防止重複依賴,後面會重點介紹transitive
排除全部的傳遞依賴,後面會重點介紹include
CommonSDK模塊的定義能夠參考settings.gradle
其餘的介紹能夠參考 依賴庫管理。
repositories
和dependencies
了嗎?他們的做用是不同的,在buildscript
裏面的那個是插件初始化環境用的,用於設定插件的下載倉庫,而外面的這個是設定工程依賴的一些模塊和遠程library的下載倉庫的。這個文件是全局的項目配置文件,裏面主要聲明一些須要加入gradle的module。
通常在setting.gradle
中主要是調用include
方法,導入工程下的各個子模塊。
那咱們在setting.gradle
裏面還能寫什麼呢?由於setting.gradle
對應的是gradle
中的Settings
對象,那查下Settings
的文檔(https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html),看下它都有哪些方法,哪些屬性,就知道在setting.gradle
能寫什麼了;
include ':AndroidDemo' include ':CommonSDK' project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')
include
調用後,生成了一個名爲:CommonSDK
的Project
對象,project(':CommonSDK')
取出這個對象,設置Project
的 projectDir
屬性。projectDir
哪裏來的?請看Project
類的文檔。
能夠在 gradle.properties 文件中配置一些變量,這些變量在這個工程下的全部module的build.gradle文件裏均可以使用。這樣就能夠把一些共用的變量放到這裏,這樣後面修改的時候就能夠只修改這個變量,不用各個模塊都要修改了。
好比咱們在 gradle.properties SDK 版本以及應用的版本號:
MIN_SDK_VERSION=21 TARGET_SDK_VERSION=22 VERSION_CODE=200100 VERSION_NAME=2.1.0 RX_ANDROID_VERSION=1.2.0
那麼在 build.gradle 中能夠經過project
進行獲取或者 "${RX_ANDROID_VERSION}"
引用:
defaultConfig { applicationId "com.example.heqiang.testsomething" minSdkVersion project.MIN_SDK_VERSION as int targetSdkVersion project.TARGET_SDK_VERSION as int versionCode project.VERSION_CODE as int versionName project.VERSION_NAME /* * as int 關鍵字是用來進行類型轉換的,由於從配置裏面讀取出來的默認是字符串 *還可使用 versionCode Integer.parseInt(project.VERSION_CODE) * */ } // 還能夠這樣用 dependencies { compile "io.reactivex:rxandroid:${RX_ANDROID_VERSION}" compile "io.reactivex:rxjava:${RX_JAVA_VERSION}" }
或者在 gradle.properties
中添加:
systemProp.versionName=1.0.0 systemProp.versionCode=100
能夠經過 System.properties
進行引用:
def code = System.properties['versionCode'] def name = System.properties['versionName']
咱們在進行一些配置的時候可能須要知道一些變量的值,這時候能夠在 build.gradle 中添加打印進行調試,好比:
defaultConfig { applicationId "com.example.hq.testsomething" minSdkVersion project.MIN_SDK_VERSION as int targetSdkVersion project.TARGET_SDK_VERSION as int versionCode project.VERSION_CODE as int versionName project.VERSION_NAME println('** build versionName=' + versionName) }
在 Gradle Console 中就能夠看到打印:
** build versionName=2.1.0
dependencies { //單文件依賴 compile files('libs/android-support-v4.jar') //某個文件夾下面所有依賴 compile fileTree(dir: 'src/android6/libs', include: ['*.jar']) compile (name:'ui', ext:'aar') compile (project(':CommonSDK')) { exclude group: "com.android.support" } provided fileTree(dir: 'src/android5/libs', include: ['*.jar']) provided 'com.android.support:support-v4:21.0.3' provided project(':main-host') }
gradle
同時支持maven
,ivy
,以maven
做爲例子:
repositories { //從中央庫裏面獲取依賴 mavenCentral() //或者使用指定的本地maven 庫 maven{ url "file://F:/githubrepo/releases" } //或者使用指定的遠程maven庫 maven{ url "https://github.com/youxiachai/youxiachai-mvn-repo/raw/master/releases" } } dependencies { //應用格式: packageName:artifactId:version compile 'com.google.android:support-v4:r13' }
對於項目依賴android library
的話,在這裏須要使用gradle mulit project機制。
Mulit project設置是gradle
約定的一種格式,若是須要編譯某個項目以前,要先編譯另一個項目的時候,就須要用到。結構以下(來自於官方文檔):
MyProject/ | settings.gradle + app/ | build.gradle + libraries/ + lib1/ | build.gradle + lib2/ | build.gradle
須要在workplace目錄下面建立settings.gradle
的文件,而後在裏面寫上:
include ':app', ':libraries:lib1', ':libraries:lib2'
例如:
include ':AndroidDemo' include ':CommonSDK' project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')
如此,gradle mutil project 就設置完畢。
對於app project若是須要應用libraries目錄下的lib1,只須要在app project的build.gradle
文件裏的依賴中這麼寫:
compile project(':libraries:lib1')
相似前面的
provided project(':main-host')
便可完成,寫完之後能夠用gradle dependencies
能夠檢查依賴情況
咱們能夠在項目的根目錄建立一個gradle配置文件config.gradle
,內容以下:
ext{ android=[ compileSdkVersion: 22, buildToolsVersion: "23.0.1", minSdkVersion: 21, targetSdkVersion: 22, versionCode: 1, versionName: "1.0" ] dependencies=[ compile:'com.android.support:support-v4:21.0.3', compile: (project(':CommonSDK')) { exclude group: "com.android.support" }, provided: fileTree(dir: 'src/android5/libs', include: ['*.jar']), provided: project(':main-host') ] }
targetSdkVersion的版本還有依賴庫的版本升級都在這裏進行統一管理,全部的module以及主項目都從這裏贊成讀取就能夠了。
在build.gradle文件中加入:
apply from:"config.gradle"
意思是全部的子項目或者全部的modules均可以從這個配置文件中讀取內容。
android節點讀取ext中android對應項,dependencies讀取dependencies對應項,若是配置有變化就能夠只在config.gradle中修改,是否是很方便進行配置的管理呢?
運行命令./gradlew <projectname>:dependencies --configuration compile
(projectname爲settings.gradle裏面配置的各個project,若是沒有配置,直接運行./gradlew dependencies --configuration compile
),會把依賴樹會打印出來,依賴樹顯示了你 build 腳本聲明的頂級依賴和它們的傳遞依賴:
仔細觀察你會發現有些傳遞依賴標註了*號,表示這個依賴被忽略了,這是由於其餘頂級依賴中也依賴了這個傳遞的依賴,Gradle會自動分析下載最合適的依賴。
Gradle容許你徹底控制傳遞依賴,你能夠選擇排除所有的傳遞依賴也能夠排除指定的依賴。
group
和module
,能夠分別單獨使用,會排除全部匹配項。// 編譯CommonSDK模塊,可是去掉此模塊中對com.android.support的依賴,防止重複依賴報錯 compile (project(':CommonSDK')) { exclude group: "com.android.support" } compile ('com.jakewharton:butterknife:8.5.1'){ exclude module: 'support-compat' exclude group: 'com.android.**.***', module: '***-***' }
Error:java.io.IOException: Duplicate zip entry
報錯。// 使用transitive屬性設置爲false來排除全部的傳遞依賴 compile project(':extras:ShimmerAndroid'){ transitive = false }
configurations.all{ resolutionStrategy{ force'org.hamcrest:hamcrest-core:1.3' } }
這樣,應用中對org.hamcrest:hamcrest-core
依賴就會變成1.3版本。
若是你想使用一個依賴的最新版本,你可使用latest.integration,好比聲明 Cargo Ant tasks的最新版本,你能夠這樣寫org.codehaus .cargo:cargo-ant:latest-integration,你也能夠用一個+號來動態的聲明:
dependencies { //依賴最新的1.x版本 compile "org.codehaus.cargo:cargo-ant:1.+" }
而後在依賴樹裏面能夠清晰的看到選擇了哪一個版本:
\--- org.codehaus.cargo:cargo-ant:1.+ -> 1.3.1
http://www.open-open.com/lib/view/open1431391503529.html
http://www.jianshu.com/p/429733dbbc34
主要藉助
android { productFlavors{ …… } }
來實現。
網上可能是相似友盟的配置,copy過來:
http://blog.csdn.net/maosidiaoxian/article/details/42000913
http://www.javashuo.com/article/p-hsxbewvv-gy.html
在AndroidManifest.xml
裏面寫上:
<meta-data android:name="UMENG_CHANNEL" android:value="Channel_ID" />
裏面的Channel_ID
就是渠道標示。咱們的目標就是在編譯的時候這個值可以自動變化。
android { productFlavors { xiaomi { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] } _360 { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"] } baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] } wandoujia { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"] } } }
或者批量修改
android { productFlavors { xiaomi {} _360 {} baidu {} wandoujia {} } productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } }
而後用 ./gradlew assembleRelease
這條命令會把Product Flavor下的全部渠道的Release版本都打出來。
assemble<Product Flavor Name>
: 容許構建指定flavor的全部APK,例如assembleFlavor1
將會構建Flavor1Debug
和Flavor1Release
兩個Variant
版本。
在上面當中,咱們也能夠指定一個默認的渠道名,若是須要的話。指定默認的值是在defaultConfig
節點當中添加以下內容:
manifestPlaceholders = [ CHANNEL_NAME:"Unspecified"]
這裏的Unspecified
換成你實際上的默認的渠道名。
使用manifestPlaceholders
的這種配置,一樣適用於manifest
的其餘配置。好比你須要在不一樣渠道發佈的apk裏面,指定不一樣的啓動Activity
。好比在豌豆莢裏面發佈的,啓動的Activity
顯示的是豌豆莢首發的界面,應用寶裏面啓動的是應用寶首發的界面(哈哈,有點壞),你就能夠對你的activity
的值使用 {activity_name}
的方式,而後在productFlavors
裏面配置這個{activity_name}
的值。
另外這裏記錄一個 productFlavors 和 applicationId 關係的小知識。
參考文檔
每一個 Android 應用均有一個惟一的應用 ID,咱們能夠在經過 productFlavors 構建的應用變體中配置不一樣的應用 ID。
android { defaultConfig { applicationId "com.example.myapp" } productFlavors { free { applicationIdSuffix ".free" } pro { applicationIdSuffix ".pro" } } }
這樣,「免費」的 applicationId 就變爲「com.example.myapp.free」。