天天看點

Android Studio Gradle的一些總結

簡介

Android Studio預設使用Gradle作為建構工具,不像Ant那樣基于XML,取而代之的是采用基于Groovy的DSL(Domain Specific Language)。

Gradle建構工具是任務驅動型的建構工具,并且可以通過各種Plugin擴充功能以适應各種建構任務。

采用約定優于配置的原則,最簡單方式是使用一個預設的目錄結構。當然目錄結構是可以自己修改的。

Gradle Build Files

建立一個Android Studio項目時,會預設生成以下Gradle相關檔案。

Project級别的build.gradle檔案

buildscript {

//編譯Gradle腳本過程中需要的依賴關系.//

    repositories {

        jcenter()
    }

//選擇JCenter repository.//

    dependencies {

        classpath 'com.android.tools.build:gradle:1.2.3'

//腳本依賴Android plugin for Gradle 1.2.3// 

    }
}

allprojects {

//你應用的依賴關系.//

    repositories {
        jcenter()
    }
}

//應用依賴jCenter repository.//
           

Module級别的build.gradle檔案

apply plugin: 'com.android.application'

//引入Android App插件.//

android {

//下面的部配置設定置Android App相關的資訊.//

    compileSdkVersion 

//編譯的SDK版本.// 

    buildToolsVersion "21.1.1"

//Build Tools版本,最好選擇版本号大于或等于compileSdkVersion的.//

    defaultConfig {

        applicationId "com.example.jessica.myapplication"

//application’s ID. 舊版本是 ‘packageName’.//

        minSdkVersion 

//需要的最小API版本.//

        targetSdkVersion 

//應用運作的API版本.//

        versionCode 

        versionName "1.0"
    }

    buildTypes {
        release {

//‘BuildTypes’ 控制你App如何編譯打包. 如果你想建立你自己的 build variants, 添加到這裡.//

            minifyEnabled true

//是否進行混淆.//

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

//混淆配置.// 

        }
    }
}

dependencies {

//當然Module需要的依賴關系.//

   compile fileTree(dir: 'libs', include: ['*.jar'])

//依賴編譯app/libs.// 

   compile 'com.android.support:appcompat-v7:21.0.3'

//依賴編譯遠端庫.//

}
           

Other Gradle Files

gradle-wrapper.properties (Gradle Version)

wrapper相關配置檔案:當其他人編譯你的項目時,即使他們沒有安裝gradle,使用./gradlew相關指令時,這個檔案會檢查正确版本的gradle是否被安裝,如有必要會幫你下載下傳正确的版本。下面會詳細講wrapper。

distributionBase=GRADLE_USER_HOME

//決定解壓後的Gradle包是存儲到工程目錄下, 還是存儲到Gradle user home directory. 
//(對于Unix machines, Gradle user home directory預設在 ~/.gradle/wrapper.)
//如果是PROJECT則zip會解壓到該工程目錄下

distributionPath=wrapper/dists

//解壓後的Gradle包存放的具體路徑.//

zipStoreBase=GRADLE_USER_HOME

zipStorePath=wrapper/dists

//下載下傳的Gradle zip包所放置的目錄//

distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

//Gradle的下載下傳位址.//
           

settings.gradle

該檔案組合你所有想建構的module。

gradle.properties (Project Properties)

這個檔案包含整個project的配置資訊。預設是空檔案,你可以添加各種屬性值到這個檔案,build.gradle中可以引用之。

local.properties (SDK Location)

這個檔案告訴Android Gradle plugin你的Android SDK安裝在哪:

sdk.dir=/Users/jessica/Library/Android/sdk
           

由于這是你本地的SDK路徑,是以這個檔案不應該加入版本控制中。

The Gradle Wrapper

Android Studio建立項目時都建議使用Gradle Wrapper來建構,這不是必須的,直接指定你本地的安裝的Gradle也行。

用wrapper的好處是當别人參與到該項目時,無須事先本地安裝Gradle或者Android Studio,當運作./gradlew相關的指令時,wrapper會檢查本地相應目錄下是否已經有對應版本的Gradle,如果沒有會幫你下載下傳正确的版本。還有對于一些持續內建的測試伺服器,不一定是安裝了Gradle的,這時候使用wrapper就能避免重新配置伺服器。

如果你想将Gradle項目轉換成基于Gradle Wrapper的,隻需要簡單的跑一下gradle wrapper即可,也可以加上–gradle-version 2.4選項來指定一個gradle的版本,–gradle-distribution-url選項指定了從哪兒下載下傳gradle,如果沒有任何選項,則會從Gradle repository下載下傳你運作wrappertask的gradle版本。你也可以将wrapper這個task寫入你的build.gradle檔案:

task wrapper(type: Wrapper) {
    gradleVersion = '2.4'
}
           

wrappertask會在你的項目根目錄下生成如下檔案:

sample/
  gradlew
  gradlew.bat
  gradle/wrapper/
    gradle-wrapper.jar
    gradle-wrapper.properties
           

這些檔案是都應該加入到版本控制中的。

如果你想更改Gradle版本,可以直接修改gradle-wrapper.properties檔案:

distributionUrl=https\://services.gradle.org/distributions/gradle--all.zip
           

或者再跑一下wrappertask重新生成這些檔案,因為wrapper腳本可能會有更新。

使用wrapper的話會忽略你本機已經安裝的gradle。

檔案可在http://services.gradle.org/distributions/找到最新版本。

關于Build variants

Build variants是product flavors和build types的組合。

buildTypes {
    debug {
        debuggable true
    }
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
productFlavors {
    demo {
        applicationId "me.zircon.test.demo"
        versionName "1.0-demo"
    }
    full {
        applicationId "me.zircon.test.full"
        versionName "1.0-full"
    }
}
           

上面的片段會組合成4種variants:demoDebug,demoRelease,fullDebug,fullRelease。

Android Studio正常左下角有一個Build Variants的面闆,裡面可以選擇你最終想編譯的版本,當選擇run一個子產品時,就是編譯的這裡選擇的版本。也可以通過指令行./gradlew assemble來編譯,編譯出的apk可以在app/build/outputs/apk裡找到,格式是app--.apk。 也有利用productFlavors來打管道包的例子。可見這篇文章。

Source Sets

我們可以在src下建立多個source set:

Android Studio Gradle的一些總結

每一個set代表一個flavor或者build type,main set所有variants都會用到。在編譯某個variants時會選擇相應set中的src和res。比如assembleDemoDebug,會組合main,demo和debug set。對于res和manifest檔案,内容會合并,如果有重名字段的,其合并優先級從低到高是:libraries/dependencies -> main src -> productFlavor -> buildType。對于src,組合成variants的set中不能存在重名檔案,即demo和Debug中不能同時存在一個A.java,但是Debug和Release中可以同時有。 當然我們也可以通過腳本中的sourceSets{ }配置目錄結構。 特别對于非約定目錄結構的工程(比如Eclipse工程),通過sourceSets{ }加以配置以便Gradle識别:

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

關于dependencies

dependencies一般有三種形式:

  • Module Dependencies
compile project(":lib")
           
  • Local Dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
           
  • Remote Dependencies

對于Remote Dependencies,書寫的格式一般是group:name:version,這個網址可以幫你在Maven Central搜尋lib并生成dependencies。

jcenter 和 Maven Central

Gradle會自動從repositories{…}幫你下載下傳編譯Remote Dependencies。

舊版本的Android Studio預設生成的repositories{ }是Maven Central,而新版本已經變成jcenter。這兩者都是互相獨立的lib倉庫,由不同的廠商托管,相較之下,jcenter有以下優勢:

  • jcenter對開發者是友好的,上傳自己的lib到jcenter很友善
  • jcenter利用CDN加速,是以下載下傳lib更快
  • jcenter類庫更全,可以認為是Maven Central的超類

并不是所有類庫都host在jcenter或者Maven Central上,有些是host在自己的Maven倉庫中,比如我們項目中所使用的twitter的crashlytics庫,它host在twitter自己的倉庫中:

repositories {
    maven { url 'https://maven.fabric.io/public' }
}
           

關于如何将自己的類庫上傳到jcenter可以參考 這篇文章。

Gradle的一些概念

我們回過頭來看看Gradle的一些概念。

Gradle腳本基于Groovy。每一個Gradle腳本執行時都會配置一種類型的對象。比如執行build.gradle會建立并配置一個Project類型的對象,而settings.gradle則配置Settings對象。相應的這個類型中的屬性和方法可以直接用在腳本中,如:file(…)傳回路徑的File對象;println name則列印該project的name。

腳本裡可以使用任何Groovy/Java的文法。比如解析AndroidManifest檔案取得VersionName:

def manifestVersionName() {
    def manifestFile = file(project.projectDir.absolutePath + '/src/main/AndroidManifest.xml')
    def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android")
    def xml = new XmlParser().parse(manifestFile)
    return xml.attributes()[ns.versionName].toString()
}
           

Project

Gradle裡面的Project的概念可以了解成Android Studio中的Module的概念,Project是指我們的建構産物(比如Jar包)或實施産物(将應用程式部署到生産環境)。一個項目可以包含一個或多個任務。

Task

Project由一個或多個Task組成,每一個Task代表了一連串原子性的操作。在Android Studio右邊的Gradle面闆或者輸入指令./gradlew tasks都能檢視目前項目所有的Task。 我們也可以用多種方式來建立一個task:

task myTask
task myTask { configure closure }
task myType << { task action }
task myTask(type: SomeType)
task myTask(type: SomeType) { configure closure }
           

Plugin

在Gradle中,所有有用的特性都是由Plugin來提供的。添加Plugin到Gradle中其實就是添加了一些新的task,域對象(如SourceSet),約定(如Java source預設放在src/main/java下),同時也會擴充一些已經存在的類型。 Plugin分兩種:腳本插件apply from: ‘other.gradle’和二進制插件apply plugin: ‘java’。

Refs

https://docs.gradle.org/current/userguide/userguide.html

http://tools.android.com/tech-docs/new-build-system

http://developer.android.com/sdk/installing/studio-build.html

本文轉自http://www.zircon.me/06-25-2015/about-gradle.html,部分改動。

繼續閱讀