android gradle使用詳解

我們知道Android studio在發(fā)布之初就使用了gradle來構建和管理Android項目,所以很多人在開發(fā)Android應用的過程中或多或少都和它打過交道,今天就給大家分享下我對gradle的一些理解,以及在Android開發(fā)中使用gradle的一些經驗。

項目自動化構建工具的發(fā)展

最早在開發(fā)的過程中是沒有項目自動化構建這個東西的,每次編譯項目的時候都是在命令行下對每個源文件執(zhí)行編譯命令,這種方式對于源文件不多的小項目還行,但是當項目比較大有成百上千個源文件需要編譯時就比較痛苦了,所以才有了一些自動化構建工具的誕生,其本質是將一些繁瑣的無須人工干預的編譯流程交由機器來完成。

Makefile

最早出現(xiàn)的構建工具是makefile,它主要用于C/C++項目,大家會發(fā)現(xiàn)Android的源碼里面用的就是這一套構建機制。makefile文件將程序編譯,鏈接,裝載(編譯原理上的東西,不熟悉的可以去翻閱相關書籍)的流程定義成一套統(tǒng)一的規(guī)則。其中就包括了:哪些源文件需要編譯,如何去編譯,依賴的庫文件,以及如何生成最終的可執(zhí)行文件等等。通過這些規(guī)則去實現(xiàn)我們的構建需求,那么當你在編譯整個工程的時候就只需要在命令行下執(zhí)行一個make命令就可以搞定了,極大的提高了項目的構建效率。

Ant

ant也是一套構建工具,主要應用于Java項目(在eclipse上開發(fā)Android項目的時候用的比較多)。它是一個將軟件編譯,測試,部署過程組織起來自動化執(zhí)行的工具。ant構建文件基于xml,每個文件對應一個唯一的project,每個project下面可以有很多的target,這些target之間存在著一定的依賴關系,當執(zhí)行某個target時需要先執(zhí)行該target的依賴。每個target里面又包含了一些task,task就是最終需要執(zhí)行的命令。

Maven

ant雖然能大幅提高構建的效率,但是也存在一些缺點,比方說ant中的組件依賴(jar包)不能跨網絡使用,為了解決這個問題,于是maven出現(xiàn)了,maven使用了強大的中央倉庫,使得項目中使用到的一些公共組件可以很方便的聯(lián)網依賴和更新,這也極大的方便了一些開源項目的使用。

Gradle

由于maven的配置過于復雜和繁瑣,于是出現(xiàn)了我們今天的主角gradle,下面給大家看下兩者配置文件的對比。

maven的配置:

<dependencies>
    <dependency>
        <groupId>com.crashlytics.sdk.android</groupId>
        <artifactId>crashlytics</artifactId>
        <version>2.5.5</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
</dependencies>

gradle的配置:

dependencies {
    compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar')
    testCompile('junit:junit:4.7')
}

Gradle

關于gradle的介紹和資料,網上有很多,這里給出我覺得寫的非常好的一篇文章:《深入理解Android之Gradle》,該文章由《深入理解Android》的作者鄧平凡撰寫,質量很高。我大致總結一下我的理解:

  1. gradle基于groovy實現(xiàn)了一套編程框架,所以我們可以在gradle配置中通過編程的方式靈活的去配置我們的構建過程。
  2. gradle還是一種DSL領域相關語言,也就是行話,比方說sourceSets代表源文件集合等。基于這些行話我們可以很方便的建立一個模板,通過這些模板可以更加方便的去配置我們的構建過程。
  3. gradle本質上執(zhí)行一系列項目構建過程,比方說Android項目里的check,build,assemble,install等。所以要更好的使用gradle需要先熟悉你正在開發(fā)項目的構建流程。

Gradle在Android中的實踐

android studio中gradle配置詳解

我們打開AndroidStudio選擇Android視圖,可以很清楚的看到當前項目下的gradle相關的配置文件,這里我們逐一介紹。


  • build.gradle(Project:nim_demo)為root project(這里我們稱項目的根目錄為root project)下的gradle配置文件,該配置文件一般用來做一些全局性的配置。
//全局配置構建工具的classpath和遠程倉庫路徑,這里一般配置為gradle的,因為項目在構建過程中需要使用gradle去執(zhí)行,當然如果你使用到了一些額外的插件,比如注解處理器,也可以放在這里。
buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.3'
    }
}
//這里是對項目中的所有project進行配置,以Android項目為例,這里的project包括項目下的各種module以及項目根目錄root project。
allprojects {
    repositories {
        jcenter()
    }
}
//這里是對該project下的所有子project進行配置,以Android項目為例,一般我們可以把一些公用的操作放在一個gradle配置文件中,然后import到各個子project的gradle中,方便使用
subprojects {
//類似于Java中的import功能,將該文件中定義的方法或變量導入后,其他gradle文件可以直接引用該gradle中的方法或變量
    apply from: 'common.gradle'
}
//定義一些變量,該變量可以被其他gradle使用
ext {
    compileSdkVersion=21
    buildToolsVersion='23.0.2'
    minSdkVersion=9
    targetSdkVersion=19
    versionCode=28
    versionName='3.0.0'
    targetCompatibility=1.7
    sourceCompatibility=1.7
}
  • build.gradle(Module:demo)為module下的gradle配置,該配置只對該module生效。
//聲明該模塊最終生成產物為apk
apply plugin: 'com.android.application'

android {
//編譯使用的sdk版本
    compileSdkVersion 23
    //使用的編譯工具版本,一般與sdk版本對應,比如sdk version為23,則buildToolVersion應選擇為23.x.x
    buildToolsVersion rootProject.buildToolsVersion
//所有flavor的默認配置
    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 23
    }
//project的簽名配置
    signingConfigs {
        debug { storeFile file("debug.keystore") }

        release {
            storeFile file('release.keystore')
            storePassword 'thisiskeystorepassword'
            keyAlias 'nim_demo'
            keyPassword 'thisiskeypassword'
        }
    }
//project的編譯類型
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }

        release {
            minifyEnabled true
            zipAlignEnabled true
            proguardFile('proguard.cfg')
            signingConfig signingConfigs.release
        }
    }
    //項目的目錄結構
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            aidl.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']

        }

    }
//lint檢查的選項
    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
    //生成dex的選項
    dexOptions {
        incremental true
        preDexLibraries false
        jumboMode true
        javaMaxHeapSize "4g"
    }
    //打包選項
    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }

}
//該project的依賴
dependencies {
//依賴本地libs目錄下的jar包
    compile fileTree(dir: 'libs', include: '*.jar')
    //依賴uikit模塊
    compile project(path: ':uikit')
}

這里的配置就是Android Gradle插件特有的配置,我們可以去官方網站上找到每個配置項的詳細說明。

  • build.gradle(Module:uikit)為uikit模塊下的配置,該配置只對uikit生效。
//聲明該模塊編譯產物為aar
apply plugin: 'com.android.library'
//其余配置與dmeo模塊類似,這里不再贅述
android {
    useLibrary 'org.apache.http.legacy'

    compileSdkVersion 23
    buildToolsVersion buildToolsVer

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res', 'res-ptr']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile fileTree(dir: 'libs', include: '*.jar')
}

  • gradle-wrapper.properties(Gradle Version)為gradle的版本配置信息。
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

當我們從github下載一個開源項目導入到Android Studio中打開時,如果本地的gradle版本與該配置文件的版本不符就會去聯(lián)網下載對應版本的gradle。由于gradle有時訪問會比較慢,所以建議將網上的項目中該配置文件的版本改成本地已經下載了的版本運行,可以節(jié)省時間。有時修改版本信息后可能會出現(xiàn)一些語法錯誤,這是本地的gradle版本不支持該語法,因此仍然需要重新下載對應的gradle版本。

  • gradle.properties(Project Properties)是與當前項目相關的一個配置文件,主要包括一些當前項目中需要用到的鍵值對信息。
#SDK下build工具的版本號
buildToolsVer=23.0.2

#app內部版本號 
verCode=16

#app外部版本號
verName=1.2

該屬性文件會被gradle插件自動加載,所以在project的gradle文件中可以直接使用。當然你也可以自定義一個屬性文件me.properties,然后在build.gradle文件中讀取。

def getVer() {
    Properties properties = new Properties()
    File file = new File(rootDir.absolutePath + "/me.properties")
    properties.load(file.newDataInputStream())
    return properties.get("verName")//為了增加可讀性,添加return
}
  • settings.gradle(Project Settins)為工程的設置文件,告訴gradle當前工程的組成部分,比如有多少個子工程或者模塊。
include ':uikit' 
include ':demo'

該工程包含兩個模塊,一個是uikit,另一個是demo。

gradle中添加自定義task

前面我們說的都是gradle的一些配置過程,它們都是Android gradle插件已經提供好了的配置選項,我們只要參考官方文檔,合理的配置就能完成絕大部分的要求,但是有時候我們的項目可能需要在構建過程中做一些特殊的處理,比方說拷貝一些文件,調試配置信息等,這就需要我們在gradle的配置中添加一些自定義的task來完成。要找到合適的添加時機,我們就必須了解gradle的工作流程。Gradle 工作流程主要包含三個階段:

  • 首先是初始化階段,一般來說就是執(zhí)行setting.gradle
  • 然后是配置階段,配置階段會解析每個project下的build.gradle,建立一個DAG有向圖來確定project中task之間的依賴關系。
  • 最后是根據(jù)之前建立的task開始執(zhí)行task。


    image

    通過以上流程,我們發(fā)現(xiàn)gradle給我們提供了一些可以插入自己task的hook。

總結

gradle的東西暫時就講這么多,后續(xù)如果有進一步的研究會再來分享。其實,對于我們來說一般能掌握到一些基本的gradle配置就可以滿足大部分的項目需求,如果需要深入理解的話,就需要我們去研究groovy的語法和gradle的用戶參考手冊,來幫助我們實現(xiàn)更復雜的需求。

參考

android gradle插件文檔

gradle官方文檔

gradle用戶手冊

深入理解Android gradle

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容