1. 程式人生 > >Android官方技術文件翻譯——Gradle 外掛使用者指南(1-3)

Android官方技術文件翻譯——Gradle 外掛使用者指南(1-3)

不知道是什麼網路問題,上午一直髮不了部落格,其他頁面基本正常,就是在寫部落格這裡,每次開啟都是響應超時。剛才用了VPN,順便試了一下,居然可以編輯。想是CDN之類的問題吧。

這次翻譯的是Gradle 外掛使用者指南,也就是Gradle上的Android外掛的官方文件。文件很長,加上最近激情不夠,翻譯得有些慢。到昨天為止,才譯到第四章。今天先發前三章。

本文譯自Android官方技術文件《Gradle Plugin User Guide》,原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide。

翻譯不易,轉載請註明CSDN部落格上的出處:

http://blog.csdn.net/maosidiaoxian/article/details/41944325

翻譯工作耗時費神,如果你覺得本文翻譯得還OK,請點一下“頂”,我在精神上會倍受鼓勵的,謝謝。翻譯如有錯訛,敬請指正。

Gradle 外掛使用者指南

簡介

本文件是 Gradle 外掛 0.9 版本的文件。在 1.0 之前,我們所介紹的早期版本可能由於不相容問題會有所不同。

新構建系統的目標

新的構建系統的目標是:
  • 可以很容易地重用程式碼和資源
  • 可以很容易地建立應用程式的幾個變種,無論是多APK分發還是不同定製版的應用程式
  • 可以很容易地配置、 擴充套件和自定義構建過程
  • 好的 IDE 整合

為什麼是 Gradle ?

Gradle 是一個先進的構建系統和構建工具,它允許通過外掛建立自定義的構建邏輯。

基於Gradle的以下特點,我們選擇了它: 
  • 域特定語言 (DSL) 來描述和處理構建邏輯
  • 構建檔案基於 Groovy ,並允許通過 DSL來混合宣告性元素,以及使用程式碼來處理 DSL 元素以提供自定義邏輯。
  • 基於 Maven 和 Ivy 的內建依賴管理。
  • 非常靈活。允許使用最佳實現,但並不強制自己的實現方式。
  • 外掛可以提供自己的 DSL 和API供構建檔案使用。
  • 良好的Tooling API 供 IDE 整合

要求

  • Gradle 版本需要 1.10,1.11或 1.12。外掛版本需要 0.11.1
  • SDK Build Tools版本要求為 19.0.0。某些功能可能需要更高版本。

基本專案

Gradle 專案在專案的根資料夾裡的build.gradle檔案中描述它的構建邏輯。

簡單的構建檔案

最簡單的 純Java專案的build.gradle如下所示:

apply plugin: 'java'

這裡配置使用了Gradle內建的 Java 外掛。該外掛提供用於構建並測試 Java 應用程式所需要的東西。

最簡單的 Android 專案的 build.gradle 則是以下內容:

buildscript {     repositories { mavenCentral()
}     dependencies {         classpath 'com.android.tools.build:gradle:0.11.1'     } } apply plugin: 'android' android {     compileSdkVersion 19
    buildToolsVersion "19.0.0"
}
在這個 Android 構建檔案中,有3個主要部分: 

buildscript { ... }配置了驅動構建的程式碼。 
在上面的這種情況中,它聲明瞭使用 Maven 中央庫,並且對一個Maven 檔案有一個類路徑依賴。這個檔案是包含 Gradle Android 外掛的 0.11.1版本的庫 
注: 這隻會影響執行構建的程式碼,不會影響專案的原始碼。專案本身需要定義它自己的倉庫和依賴關係。稍後會提及這部分。

然後,和先前的提到的 Java 外掛一樣,這裡配置使用了 android外掛。 

最後, android { ... }配置了用於 android 構建的所有引數。這是Android DSL的入口。
預設情況下,只需要配置編譯目標,以及build-tools的版本。它通過compileSdkVersionbuildtoolsVersion屬性來完成。 編譯目標相當於舊的構建系統中project.properties 檔案內的target屬性。這個新的屬性可以設定為一個 int 值 (表示api 級別),或者是和以前的target的值一樣,設定為字串。

重要提示:你應該只配置使用這個android外掛。如果同時配置使用了java外掛也會導致構建錯誤。

注:您還需要一個local.properties檔案,通過sdk.dir屬性來設定 SDK 的位置,並且所設定的這個SDK要求存在。 
或者,您也可以設定一個ANDROID_HOME環境變數。這兩種方法之間沒什麼差別,你喜歡,你選擇。

專案結構

上述的基本構建檔案要求有一個預設的資料夾結構。Gradle 遵循約定大於配置的概念,在可能的情況下提供了合理的預設選項值。
基本專案開始於兩個名為“source sets”的元件。即主原始碼和測試程式碼。它們分別在:
  • src/main/
  • src/androidTest/
裡面的每個資料夾中都存在對應的原始碼元件的資料夾。
對於 Java 和 Android 外掛,Java 原始碼和 Java 資源的位置如下: 
  • java/
  • resources/
對於Android 外掛,Android所特有的額外的檔案和資料夾是:
  • AndroidManifest.xml
  • res/
  • assets/
  • aidl/
  • rs/
  • jni/
注: src/androidTest/AndroidManifest.xml是不需要的,因為它會被自動建立。

配置專案結構

When the default project structure isn’t adequate, it is possible to configure it. 根據 Gradle 文件,為一個Java 專案重新配置 sourceSets可以通過如下方法實現:

sourceSets {     main { java { srcDir 'src/java'
}
resources {
srcDir 'src/resources'
}
} }

注: srcDir實際上會將給定的資料夾新增到現有的原始檔夾列表中 (這在Gradle 文件中沒有提及,但這是實際的行為)。

如果要替換預設的原始檔夾,您就要使用傳入一個路徑陣列的srcDirs來代替。以下是使用涉及的物件的另一種不同的方法:

sourceSets {     main.java.srcDirs = ['src/java']     main.resources.srcDirs = ['src/resources'] }

欲瞭解更多資訊,請參閱 Gradle 文件中關於 Java 外掛的內容,見這裡

Android 外掛使用類似的語法,但因為它使用它自己的sourceSets,所以在android物件裡面來實現。 
這裡有一個例子,使用舊的專案結構的主原始碼並重新對映androidTest sourceSet 到tests資料夾:

android {    sourceSets {        main {manifest.srcFile 'AndroidManifest.xml'java.srcDirs = ['src']
resources.srcDirs = ['src']aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']assets.srcDirs = ['assets']
}
androidTest.setRoot('tests')}}

注意: 因為舊的結構把所有原始檔 (java、 aidl、 renderscript和 java 資源) 都放在相同的資料夾中,我們需要重新對映sourceSet的所有這些新元件到相同的src資料夾中。
注意: setRoot()會將整個sourceSet (和它的子資料夾) 移到一個新的資料夾中。這將移動src/androidTest/*tests/*
下。這是 Android 專用的,不適用於 Java sourceSets。 

這也是一個“遷移”的例子。

構建任務

常規任務

在構建檔案中配置使用一個外掛,將自動建立一系列要執行的構建任務。Java 外掛和 Android 外掛都是。 約定的任務如下:
  • assemble
    組裝專案的輸出的任務
  • check
    執行所有檢查的任務。
  • build
    這個任務將執行assemblecheck
  • clean
    這個任務將清理專案的輸出
assemblecheckbuild這些任務,實際上不做任何事情。他們是錨記任務,用於讓外掛新增實際的任務去做這些事情。這允許您能夠呼叫同樣的任務,無論專案的型別是什麼,或者是配置使用了什麼外掛 


例如,配置使用findbugs外掛將建立一個新的任務和使check任務依賴於它,使得每當呼叫check任務時都會呼叫到它。

您可以從命令列中執行下面的命令來獲取更高級別的任務: 
gradle tasks
下面的命令可以得到一個完整的任務列表,並且看到任務執行之間的依賴關係:
gradle tasks --all
注: Gradle 會自動監視一個任務所宣告的輸入和輸出。
在沒有變化的情況下,執行兩次build會使 Gradle 報告所有任務為UP-TO-DATE狀態,這個狀態意味著沒有任何事情需要執行。這允許任務正確地相互依賴而無需不必要的構建操作。

Java 專案任務

Java 外掛主要建立兩個任務,它們是主要錨記任務的依賴任務:
  • assemble
    • jar
      這個任務將建立輸出。
  • check
    • test
      這個任務將執行測試。
jar任務本身會直接或間接地依賴其他任務: 例如,classes任務用於編譯 Java 程式碼。
testClasses任務用於編譯測試,但它很少會被呼叫,因為test任務依賴於它 (以及classes任務)。

一般情況下,你將可能永遠只調用assemblecheck,而無視其他任務。 

在這裡,你可以看到Java 外掛的所有任務和對它們的描述。

Android 任務

Android 的外掛使用相同的約定配置以相容其他外掛,並添加了另外的錨記任務:
  • assemble
    組裝專案的輸出的任務
  • check
    執行所有檢查的任務。
  • connectedCheck
    執行需要一個已連線的裝置或模擬器的檢查。它們將在所有已連線的裝置上並行執行。
  • deviceCheck
    使用 API 連線到遠端裝置執行檢查。這一個是在 CI 伺服器上使用的。
  • build
    這項任務將執行assemble 和 check
  • clean
    這個任務將清理專案的輸出
新的錨記任務是有必要的,以便能夠執行定期的檢查而無需連線的裝置。
注意到,build任務不依賴於deviceCheckconnectedCheck

Android 專案具有至少兩個輸出: debug版本的APK 和release版本的 APK。這裡的每一個輸出都有自己的錨記任務,以便單獨構建它們: 
  • assemble
    • assembleDebug
    • assembleRelease
它們兩個都依賴於執行構建一個 APK所需的多個步驟的其他任務。assemble任務取則依賴於這兩個任務,所以呼叫 assemble 將會構建出這兩個 APKs。

提示:在命令列上,Gradle 支援任務名稱的駝峰命名法的簡寫。例如: 
gradle aR
相當於輸入
gradle assembleRelease
只要沒有其他任務匹配 “aR” 

check錨記任務有它們自己的依賴項: 
  • check
    • lint
  • connectedCheck
    • connectedAndroidTest
    • connectedUiAutomatorTest (暫未實現)
  • deviceCheck
    • 這個任務依賴於當其他外掛實現了測試擴充套件點時建立的任務。
最後,該外掛為所有構建型別 (debugreleasetest)建立了omstal/uninstall 任務,只要他們可以被安裝(需要簽名)。

基本的構建定製

Android 外掛提供了大量的 DSL,以通過構建系統直接地自定義大部分事情。

清單條目

通過 DSL 可以配置以下清單條目:
  • minSdkVersion
  • targetSdkVersion
  • versionCode
  • versionName
  • 用於測試應用程式的包名
  • Instrumentation test runner
示例:

android {     compileSdkVersion 19
    buildToolsVersion "19.0.0"
    defaultConfig { versionCode 12
versionName "2.0"
minSdkVersion 16
targetSdkVersion 16
} }

android元素的內部的defaultConfig元素是定義所有這些配置的地方。 以前版本的 Android 外掛使用packageName來配置清單的“packageName”屬性。 從 0.11.0開始,你應該在 build.gradle 中使用 applicationId 來配置清單中的“packageName”條目。 它消除了應用程式的包名(指它的 ID)和java 包名之間的所引起的混亂。 

在構建檔案中描述它的強大之處是它可以是動態的。 
例如,可以從檔案中的某處或使用一些自定義的邏輯讀取版本資訊: 

def computeVersionName() {     ... } android {     compileSdkVersion 19     buildToolsVersion "19.0.0"     defaultConfig {         versionCode 12 versionName computeVersionName()
minSdkVersion 16
targetSdkVersion 16
} }
注意: 不要使用在作用域內可能與已存在的getter函式有衝突的函式名稱。例如 defaultConfig { ...} 例項呼叫 getVersionName() 時將自動使用 defaultConfig.getVersionName() 的 getter 方法,而不是自定義的方法。
如果一個屬性未通過 DSL 來設定,它將使用預設值。下表描述了對於未設定的屬性的處理方式。
 屬性名稱  DSL 物件中的預設值  預設值
 versionCode  -1  如果在清單中存在,則使用清單中的值
 versionName  null  如果在清單中存在,則使用清單中的值
 minSdkVersion  -1  如果在清單中存在,則使用清單中的值
 targetSdkVersion  -1  如果在清單中存在,則使用清單中的值
 applicationId  null  如果在清單中存在,則使用清單中的值
 testApplicationId  null  applicationId + “.test”
 testInstrumentationRunner  null  android.test.InstrumentationTestRunner
 signingConfig  null  null
 proguardFile  N/A (只設置)  N/A (只設置)
 proguardFiles  N/A (只設置)  N/A (只設置) 


第二列的值是很重要的,如果您在構建指令碼中使用自定義邏輯查詢這些屬性的話。例如,您可以編寫:
if (android.defaultConfig.testInstrumentationRunner == null) {     // assign a better default... }
如果值仍然為null,那麼在構建的時候它將會被設為第三列中的實際預設值,但是由於 DSL 元素不包含此預設值,因此您無法查詢它。
這是為了防止解析應用程式的清單,除非真的很需要。

構建型別

預設情況下,Android 外掛自動將專案設定為生成應用程式的的debug和release版本。 這兩個版本的不同,大多是圍繞在除錯一個安全的(非開發版的)裝置的能力,以及 apk 怎麼簽名。

除錯版本使用自動建立的金鑰/證書籤名,並且金鑰/證書的使用者名稱/密碼是已知的(以防止構建過程中需要相關的資訊)的。release版本在構建的時候不會進行簽名,需要在之後進行簽名。

這個配置是通過一個叫BuildType的物件來完成的。預設情況下,2 個例項會被建立,分別是debug版和release版。

Android 外掛允許自定義這兩個例項,以及建立其他的構建型別。它通過buildTypes DSL 容器來實現:

android {     buildTypes { debug {     applicationIdSuffix ".debug"
}         jnidebug.initWith(buildTypes.debug)         jnidebug {             packageNameSuffix ".jnidebug"             jniDebuggable true         }     } }

上面的程式碼段可實現以下操作:
  • 配置預設的Debug Build Type
    • 設定包名為<app appliationId>.debug,以便能夠在相同的裝置上安裝debugrelease兩個版本的apk
  • 建立一個叫jnidebug的新的BuildType物件 ,並將其配置為debug生成型別的一個副本。
  • 通過啟用 JNI 元件的debug構建,並新增不同的包字尾,繼續配置jnidebug
建立新的 Build Types 就是簡單地在buildTypes下新增一個新的元素,然後呼叫 initWith()或者是使用一個閉包來配置。

以下是可能用到的屬性和它們的預設值: 

 屬性名稱  用於 debug的預設值  用於 release/其他 的預設值
 debuggable  true  false
 jniDebuggable  false  false
 renderscriptDebuggable  false  false
 renderscriptOptimLevel  3  3
 applicationIdSuffix  null  null
 versionNameSuffix  null  null
 signingConfig  android.signingConfigs.debug  null
 zipAlignEnabled  false  true
 minifyEnabled  false  false
 proguardFile  N/A (只設置)  N/A (只設置)
 proguardFiles  N/A (只設置)  N/A (只設置)


除了這些屬性,Build Types還會影響到構建的程式碼和資源。
對每個Build Type都會建立一個自動匹配的sourceSet,預設位置為 
src/<buildtypename>/
這意味著Build Type的名字不能為main或者是androidTest (這是外掛所強制的),並且它們之間必須是唯一的。

與任何其他source set一樣,生成型別的source set的位置也是可以重新設定的: 
android {     sourceSets.jnidebug.setRoot('foo/jnidebug') }
此外,對於每個Build Type,會建立一個新的assemble<BuildTypeName>任務。 

已經提到過的assembleDebugassembleRelease這兩個任務,這裡也會講一下它們是怎麼來的。當debugreleaseBuild Types被預建立的時候,他們的任務也會被自動建立。然後,

上面的build.gradle片段也會生成一個assembleJnidebug任務,並且assemble將會依賴於它,就像它依賴於assembleDebugassembleRelease任務一樣。 

提示: 請記住您可以輸入gradle aJ來執行assembleJnidebug任務。

可能會用到的情況: 
  • release模式下不需要,但debug模式下需要的許可權
  • 自定義的debug實現
  • 為除錯模式使用不同的資源 (例如某個資源的值與簽名證書相繫結時)。
BuildType的程式碼和資源通過以下方式被使用:
  • manifest將被合併到應用程式的manifest中
  • 程式碼只是作為另一個原始檔夾來起作用
  • 資源將覆蓋main裡面的資源,並替換已經存在的值。

簽名配置

對應用程式進行簽名,要求如下:
  • 一個 keystore
  • 一個 keystore 的密碼
  • 一個 key 的別名
  • 一個 key 的密碼
  • 儲存型別
簽名檔案的位置,key的名稱,以及這兩個密碼和儲存型別,一起構成了一個簽名配置 ( SigningConfig型別) 

預設情況下,有一個debug的配置,配置使用了一個debug keystore。這個keystore使用了一個已知的key和一個已知的密碼。 
這個debug keystore 位於$HOME/.android/debug.keystore,並且會在不存在時被建立。debug Build Type被設定為自動使用此debug

SigningConfig
你也可以建立其他配置,或者自定義某個預設的內建配置。通過signingConfigs DSL 容器來實現:
android {     signingConfigs {         debug {             storeFile file("debug.keystore")         }         myConfig {             storeFile file("other.keystore")             storePassword "android"             keyAlias "androiddebugkey"             keyPassword "android"         }     }     buildTypes {         foo {             debuggable true             jniDebuggable true             signingConfig signingConfigs.myConfig         } } }
上面的程式碼段把debug keystore的位置修改為在專案的根位置下。這會自動影響到任何設定為使用它的Build Types,在這裡,影響到的是debug Build Type

程式碼的程式碼還建立了一個新的Signing Config和使用新配置的新的Build Type 。

注:只有位於預設位置下的debug keystores才會被自動建立。如果debug keystore的位置被更改了,它將不會在需要時自動建立。建立一個使用一個不同的名稱SigningConfig,但使用了預設的debug keystore的路徑,它也會被自動建立。換句話說,會不會被自動建立與keystore的路徑有關,而與配置名稱無關。

注: keystore的路徑通常使用專案根目錄的相對路徑,但也可以是使用絕對路徑,儘管這不推薦 (除了自動建立的debug keystore)。 注意: 如果您將這些檔案加入版本控制,您可能不希望這些檔案中有你的密碼。下面的 Stack Overflow 連結顯示瞭如何從控制檯或環境變數中讀取值的方法。 我們會在以後更新本指南補充更詳細的資訊。

執行ProGuard

ProGuard 是通過 Gradle plugin for ProGuard version 4.10來進行支援的。ProGuard 外掛會被自動配置使用,並且如果Build Type通過minifyEnabled屬性配置為執行ProGuard,對應的任務將被自動建立。 android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }
    productFlavors {         flavor1 {
        }         flavor2 {             proguardFile 'some-other-rules.txt'
        }     }
} 變種使用他們的構建型別中所宣告的規則檔案,product flavors(定製版本)則使用flavor中宣告的規則檔案。 這裡有 2 個預設的規則檔案
  • proguard-android.txt
  • proguard-android-optimize.txt
它們位於 SDK 中。使用getDefaultProguardFile()將返回的檔案的完整路徑。它們除了是否啟用優化之外,其它都是相同的。