Gradle總結(jié)

0x00 前言

Android studio默認(rèn)使用Gradle構(gòu)建Android工程。我之前有花一段時(shí)間研究Gradle,在此總結(jié)一下卒落!
Gradle跟ant/maven一樣导绷,是一種依賴管理/自動化構(gòu)建工具钦购。但是跟ant/maven不一樣葵萎,它并沒有使用xml語言羡忘,而是采用了Groovy語言(語法類似于Java),這使得它更加簡潔滨嘱、靈活,更加強(qiáng)大囊扳。
Gradle的安裝略铣减,百度一大堆劣针。

0x01 HelloWorld

先寫個(gè)hello world吧!

task hello << {
    println 'Hello world!'
}

執(zhí)行段語句:gradle -q hello,-q表示不顯示log,相應(yīng)的還可以 -info-debug來查看詳細(xì)的log信息唤冈。

LogLevel

然后輸出的內(nèi)容是:Hello world!
這就是一個(gè)簡單的gradle文件。里面定義了一個(gè)task:hello楼雹。執(zhí)行打印任務(wù)。
當(dāng)使用gradle命令行執(zhí)行task時(shí),每個(gè)task只會被執(zhí)行一次崎场,所以gradle test test和gradle test命令的執(zhí)行結(jié)果是一模一樣的。

0x02 Gradle Plugin

看了上面的例子,我們知道如何定義一個(gè)任務(wù)燕酷,但是在Android開發(fā)時(shí)我們看到的Gradle并沒有定義task声诸。因?yàn)樵贏ndroid中我們默認(rèn)添加了Gradle的Android插件:apply plugin: 'com.android.application'泻肯。 com.android.application中默認(rèn)定義了我們一些常用的task:

build:    完整編譯項(xiàng)目稚铣,包含編譯,測試和創(chuàng)建jar包  
clean:    刪除build目錄 
assemble:  編譯和創(chuàng)建jar包
check:    編譯和測試代碼

我們在一個(gè)gradle中可以使用多個(gè)插件惕医。正如我們的項(xiàng)目使用crashlytics進(jìn)行bug收集統(tǒng)計(jì)耕漱,那么我們的項(xiàng)目中還得依賴apply plugin: 'io.fabric'插件。

0x03 Android Gradle

在Android Studio新建Android項(xiàng)目現(xiàn)在默認(rèn)使用gradle構(gòu)建抬伺。使用gradle構(gòu)建在規(guī)范的目錄結(jié)構(gòu)與以前ADT生成的有很大的不同了螟够。Gradle要求的一些規(guī)范:工程源碼位于$workspace/app/src/main/java,測試代碼位于$workspace/app/src/test/java沛简。所有位于$workspace/app/src/main/res文件都被包含到j(luò)ar包中作為資源文件齐鲤,所有的輸出文件都會放在build目錄里面,jar文件放在$workspace/app/build/libs目錄下椒楣。
詳細(xì)目錄咱們可以通過命令gradlew app:sourceSets來查看:

main                           
----                           
Compile configuration: compile 
build.gradle name: android.sourceSets.main
Java sources: [app\src\main\java]
Manifest file: app\src\main\AndroidManifest.xml
Android resources: [app\src\main\res]
Assets: [app\src\main\assets]  
AIDL sources: [app\src\main\aidl]
RenderScript sources: [app\src\main\rs]
JNI sources: [app\src\main\jni]
JNI libraries: [app\src\main\jniLibs]
Java-style resources: [app\src\main\resources]

對于添加工程依賴也方便了很多给郊,咱們可以通過dependencies來依賴工程,依賴生成的文件路徑為:$workspace/app/build/intermediates/exploded-aar/***捧灰。依賴格式如下:

dependencies {
    compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
}
縮寫形式 “group:name:version”.
dependencies {
    compile 'org.hibernate:hibernate-core:3.6.7.Final'
}

note:-x命令用來排除一些命令的執(zhí)行淆九,比如gradle build -x ext,會在編譯的時(shí)候不執(zhí)行ext任務(wù)毛俏,即使build task依賴ext也不會執(zhí)行炭庙, 但ext所依賴的task如果被其他task依賴是會執(zhí)行的。
dependenciesDSL 元素是標(biāo)準(zhǔn)的 Gradle API 的一部分煌寇,不屬于android 元素內(nèi)焕蹄。

dependencies {
    compile files('libs/test.jar')
}

0x04 Gradlew

在項(xiàng)目的根目錄下我們看到有g(shù)radlew/gradlew.bat文件,gradlew代表 gradle wrapper阀溶,意思是gradle的一層包裝腻脏,大家可以理解為在這個(gè)項(xiàng)目本地就封裝了gradle,即gradle wrapper银锻, 在$workspace/gradle/wrapper/gralde-wrapper.properties文件中聲明了它指向的目錄和版本永品。只要下載成功即可用grdlew wrapper的命令代替全局的gradle命令。第一次執(zhí)行g(shù)radlew *時(shí)系統(tǒng)會下載創(chuàng)建項(xiàng)目時(shí)使用的gradle環(huán)境击纬,時(shí)間會比較長鼎姐。下載完后就可以直接像gradle一樣使用了。

省略寫法:gradle assembleRelease --> gradle aR

gradlew tasks
gradlew tasks --all
可以得到一個(gè)完整的任務(wù)列表,并且看到任務(wù)運(yùn)行之間的依賴關(guān)系炕桨。

0x05 Gradle Build

Gradle編譯過程如圖:


build.png

我們可以查看gradle執(zhí)行過程饭尝,比如我們要編譯一個(gè)welove渠道的release包,執(zhí)行gradle aWR >>1.txt谋作,>>1.txt表示將打印的內(nèi)容重定向到記事本中芋肠,得到的內(nèi)容:

:app:preBuild UP-TO-DATE
:app:preWeloveReleaseBuild UP-TO-DATE
:app:checkWeloveReleaseManifest
:app:preWeloveDebugBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72200Library UP-TO-DATE
:app:preWeloveDebugAndroidTestBuild UP-TO-DATE
:app:prepareComAndroidSupportMultidex101Library UP-TO-DATE
:app:prepareComAndroidSupportRecyclerviewV72200Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42200Library UP-TO-DATE
:app:prepareWeloveReleaseDependencies
:app:compileWeloveReleaseAidl UP-TO-DATE
:app:compileWeloveReleaseRenderscript UP-TO-DATE
:app:generateWeloveReleaseBuildConfig UP-TO-DATE
:app:generateWeloveReleaseAssets UP-TO-DATE
:app:mergeWeloveReleaseAssets UP-TO-DATE
:app:generateWeloveReleaseResValues UP-TO-DATE
:app:generateWeloveReleaseResources UP-TO-DATE
:app:mergeWeloveReleaseResources UP-TO-DATE
:app:processWeloveReleaseManifest UP-TO-DATE
:app:processWeloveReleaseResources UP-TO-DATE
:app:generateWeloveReleaseSources UP-TO-DATE
:app:compileWeloveReleaseJavaWithJavac UP-TO-DATE
:app:compileWeloveReleaseNdk UP-TO-DATE
:app:compileWeloveReleaseSources UP-TO-DATE
:app:lintVitalWeloveRelease
:app:processWeloveReleaseJavaRes UP-TO-DATE
:app:transformResourcesWithMergeJavaResForWeloveRelease UP-TO-DATE
:app:transformClassesAndResourcesWithProguardForWeloveRelease UP-TO-DATE
:app:collectWeloveReleaseMultiDexComponents UP-TO-DATE
:app:transformClassesWithMultidexlistForWeloveRelease UP-TO-DATE
:app:transformClassesWithDexForWeloveRelease UP-TO-DATE
:app:mergeWeloveReleaseJniLibFolders UP-TO-DATE
:app:transformNative_libsWithMergeJniLibsForWeloveRelease UP-TO-DATE
:app:validateReleaseConfigSigning
:app:packageWeloveRelease UP-TO-DATE
:app:zipalignWeloveRelease UP-TO-DATE
:app:assembleWeloveRelease

BUILD SUCCESSFUL

Total time: 46.918 secs

對比上圖可以體會gradle打包的過程!
0x06 Gradle Demo
==
放出我們項(xiàng)目工程的gradle遵蚜,刪除部分關(guān)鍵信息帖池,給大家做個(gè)參考,如下:

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "***"
        minSdkVersion 10
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }

    // 配置keystore簽名
    signingConfigs {
        releaseConfig {
            storeFile file('release-key.keystore')
            keyAlias "releasekey"
            storePassword "Replace Valid Store Password"
            keyPassword "Replace Valid Key Password"
        }
    }

    buildTypes {
        debug {

        }

        release {
            minifyEnabled true  // 進(jìn)行混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.releaseConfig
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    // 平臺定制
    productFlavors {
        welove {}
    }

    lintOptions {
        ignoreWarnings true // 只報(bào)告錯(cuò)誤
        checkReleaseBuilds true    // release構(gòu)建時(shí)issus的嚴(yán)重級為fatal吭净,若發(fā)現(xiàn)了致命(fatal)的問題睡汹,則中止構(gòu)建
        abortOnError false  // 當(dāng)lint發(fā)現(xiàn)錯(cuò)誤時(shí)停止 gradle構(gòu)建
    }

    // 通過查看打包順序發(fā)現(xiàn)打welove的Release包時(shí),第三步就是執(zhí)行checkWeloveReleaseManifest
    // 而且在打Debug包時(shí)不會執(zhí)行checkWeloveReleaseManifest寂殉,為了自動執(zhí)行releaseCheck 增加以下代碼
    tasks.whenTaskAdded { task ->
        if (task.name == 'checkWeloveReleaseManifest') {
            task.dependsOn releaseCheck
        }
    }
}

dependencies {
    // 編譯libs目錄下的所有jar包
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:support-v4:22.0.0'
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.android.support:recyclerview-v7:22.0.0'
    compile 'com.android.support:multidex:1.0.1'
    compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
        transitive = true
    }
}

import java.util.regex.Pattern
task releaseCheck <<{
    // 檢查 baidu api key 是不是有效值
    def baiduApiFile = file("$workspace/tools/WeloveConstants.java")
    def baiduApiFilePattern = Pattern.compile("\\s*public static final String BAIDU_MAP_API_KEY = ResourceUtil.getStr\\(R.string.(.*)\\)")
    def baiduApiFileMatcher = baiduApiFilePattern.matcher(baiduApiFile.getText())
    if (baiduApiFileMatcher.find()){
        def baiduApiUrl = baiduApiFileMatcher.group(1)
        if (!baiduApiUrl.equals("str_baidu_map_api_key")){
            throw new GradleException(baiduApiFile.toString() + " Contain Invalid Baidu API Key ")
        }
    }else {
        throw new GradleException(baiduApiFile.toString() + " Contain Invalid Baidu API Key ")
    }
}

因?yàn)槭褂胏rashlytics囚巴,所以根目錄的build.gradle文件也貼出來:

buildscript {
    repositories {
        jcenter()
        maven { url 'https://maven.fabric.io/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'io.fabric.tools:gradle:1.+'
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.fabric.io/public' }
    }
}

0x07 參考資料

Gradle 官方文檔翻譯: 文檔一文檔二
Android Gradle插件: 文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末友扰,一起剝皮案震驚了整個(gè)濱河市彤叉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌村怪,老刑警劉巖秽浇,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異甚负,居然都是意外死亡柬焕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門梭域,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斑举,“玉大人,你說我怎么就攤上這事病涨「荤瑁” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵既穆,是天一觀的道長赎懦。 經(jīng)常有香客問我,道長循衰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任褐澎,我火速辦了婚禮会钝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己迁酸,他們只是感情好先鱼,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奸鬓,像睡著了一般焙畔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上串远,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天宏多,我揣著相機(jī)與錄音,去河邊找鬼澡罚。 笑死伸但,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的留搔。 我是一名探鬼主播更胖,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼隔显!你這毒婦竟也來了却妨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤括眠,失蹤者是張志新(化名)和其女友劉穎彪标,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哺窄,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捐下,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萌业。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坷襟。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖生年,靈堂內(nèi)的尸體忽然破棺而出婴程,到底是詐尸還是另有隱情,我是刑警寧澤抱婉,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布档叔,位于F島的核電站,受9級特大地震影響蒸绩,放射性物質(zhì)發(fā)生泄漏衙四。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一患亿、第九天 我趴在偏房一處隱蔽的房頂上張望传蹈。 院中可真熱鬧押逼,春花似錦、人聲如沸惦界。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沾歪。三九已至漂彤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間灾搏,已是汗流浹背挫望。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留确镊,地道東北人士骤。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像蕾域,于是被迫代替她去往敵國和親拷肌。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評論 25 707
  • 參考資料:http://gold.xitu.io/post/580c85768ac247005b5472f9htt...
    zhaoyubetter閱讀 10,979評論 0 6
  • 第四章 山上論神功 這一坐便坐到了子夜旨巷,“哈哈哈巨缘,原來是這樣一個(gè)‘無為’!哈哈哈”采呐!楚越陽...
    起霧了么閱讀 257評論 0 1
  • 詩歌天生不能生活在喧囂之中若锁, 不能生長在過分現(xiàn)代的大生活中 , 詩歌是絲綢斧吐,散文是棉布又固, 有的時(shí)候我們熱愛絲綢的撫...
    迪ba閱讀 209評論 0 0
  • 《北風(fēng)》中仰冠,我聽出兩個(gè)字——初心 文¦錢黎潔 閨蜜呀,同學(xué)呀蝶糯,朋友等洋只,同齡人的孩子這幾年陸續(xù)要么高考,要么出國昼捍,朋...
    錢錢show生活閱讀 680評論 0 1