詳解Android 開發(fā)中as或者idea對(duì)gradle的使用
今年三月來的深圳,五月份要上渠道包,所以使用上了Android Gradle打包方式,從此與IDEA(Android Studio的前身)結(jié)緣,用IDEA也有半年了,解決問題挺也蠻多。 應(yīng)水群格格備胎們(老四——鴨鴨,老五——貓咪,老六——rose,老七——avfun[這都是xUtils群的技術(shù)精英])的要求,總結(jié)一下 IDEA Gradle 使用的原理,讓大家都用上 IDEA(Android Studio,已下統(tǒng)稱 IDEA)。
寫這個(gè)我不會(huì)手把手教你怎么做,我只會(huì)告訴你,這里為什么會(huì)這樣子,至于后面怎么做,你看著辦。
自動(dòng)編譯組件
目前Android開發(fā)的主流開發(fā)工具是 Eclipse 和 IDEA
目前主流的自動(dòng)化打包工具時(shí) ant,maven,gradle。
maven工具中有自己的依賴倉(cāng)庫維護(hù),很多開源支持包在上面都有維護(hù)(國(guó)內(nèi)的除外)
gradle是近年來發(fā)展起來自動(dòng)化構(gòu)建應(yīng)用,解決 ant 構(gòu)建上的繁瑣代碼,并且也支持讀取maven的配置形式,依賴maven的支持包結(jié)構(gòu)
好了,平時(shí)你們使用 eclipse 發(fā)布的時(shí)候,不要說你沒用過自動(dòng)構(gòu)建,eclipse 的 android項(xiàng)目是用ant的構(gòu)建方式。如果你要加渠道發(fā)布,你就需要自己寫 ant 的腳本。
maven自動(dòng)構(gòu)建,目前大多數(shù)用在 javaweb 項(xiàng)目,安卓項(xiàng)目用的不多。
eclipse 的構(gòu)建應(yīng)用大多使用 ant,maven,gradle也有相關(guān)支持。Android的項(xiàng)目默認(rèn)使用 ant 進(jìn)行構(gòu)建
在 IDEA 中,可以使用 ant 方式構(gòu)建 android應(yīng)用,也能使用 gradle 方式構(gòu)建,目前主流支持都是 gradle 方式。
IDEA 默認(rèn)使用 gradle 工具做 android 的構(gòu)建程序,你試試在新建應(yīng)用的時(shí)候選擇 Application Module 而不是 Gradle:Android Module 看看,你會(huì)發(fā)現(xiàn),工程項(xiàng)目和 eclipse 沒什么區(qū)別。而且包含 ant 的腳本文件。(如下圖)
Gradle Module原理
IDEA 支持 ant,maven,gradle 工具來構(gòu)建引用。目前 Android 應(yīng)用在 as下編碼基本使用 gradle 進(jìn)行構(gòu)建,本章將基于這個(gè)思路講解那些內(nèi)容屬于 IDEA,那些內(nèi)容屬于 gradle 。
首先,我們建立一個(gè) Gradle:Android Module 來看看 Gradle 項(xiàng)目結(jié)構(gòu)。
得到的目錄結(jié)構(gòu)如下:
其中根目錄是一個(gè)project,下面的app目錄是其中一個(gè)module。
.gradle gradle項(xiàng)目產(chǎn)生文件(自動(dòng)編譯工具產(chǎn)生的文件) .idea IDEA項(xiàng)目文件(開發(fā)工具產(chǎn)生的文件) app 其中一個(gè)module,復(fù)用父項(xiàng)目的設(shè)置,可與父項(xiàng)目擁有相同的配置文件 build 自動(dòng)構(gòu)建時(shí)生成文件的地方 gradle 自動(dòng)完成gradle環(huán)境支持文件夾 .gitignore git源碼管理文件 build.gradle gradle 項(xiàng)目自動(dòng)編譯的配置文件 gradle.properties gradle 運(yùn)行環(huán)境配置文件 gradlew 自動(dòng)完成 gradle 環(huán)境的linux mac 腳本,配合gradle 文件夾使用 gradlew.bat 自動(dòng)完成 gradle 環(huán)境的windows 腳本,配合gradle 文件夾使用 local.properties Android SDK NDK 環(huán)境路徑配置 *.iml IDEA 項(xiàng)目文件 setting.gradle gradle 項(xiàng)目的子項(xiàng)目包含文件 .gradle .idea 是在分別在 gradle ,IDEA 運(yùn)行時(shí)候會(huì)生成的文件,一般這樣的文件也不會(huì)納入源代碼管理之中。 app文件夾,是其中一個(gè)module,里面的文件內(nèi)容與父類差不多,若沒有定義,則在項(xiàng)目中使用父類的設(shè)置(意思就是,里面也能包含build.gradle、gradle.properties、setting.gradle 等相關(guān)gradle文件,怎么理解?其實(shí)每一層都是一個(gè)module,整個(gè)項(xiàng)目是一個(gè)大的 module 而已) gradle 文件夾,用于保存gradle 下載路徑的配置文件位置,用于沒有g(shù)radle環(huán)境的環(huán)境初始化使用 build.gradle 項(xiàng)目的編譯環(huán)境配置,比如制定項(xiàng)目依賴的lib包。 gradle.properties 配置gradle運(yùn)行環(huán)境的文件,比如配置gradle運(yùn)行模式,運(yùn)行時(shí)jvm虛擬機(jī)的大小 gradlew && gradlew.bat 代替gradle 命令實(shí)現(xiàn)自動(dòng)完成gradle環(huán)境搭建。配合gradle文件夾的內(nèi)容,會(huì)降到IDEA如何搭配gradlew使用。 local.properties 配置android NDK,SDK的地方,恩,非android項(xiàng)目可能沒有這個(gè)文件,這個(gè)路徑根據(jù)不同想電腦不同,一般也不會(huì)納入源代碼管理之中,一般可以寫一個(gè)local.properties.simple 文件,告知需要修改該文件名并寫上本地SDK NDK 路徑。simple文件納入源碼管理之中。 setting.gradle 子項(xiàng)目包含文件,聲明當(dāng)前目錄下含有什么module,當(dāng)然你的app底下加上這樣的文件,也能繼續(xù)在app底下加module。和我第點(diǎn)說的,整個(gè)project就是一個(gè)大的module,每個(gè)module下面還能包含相應(yīng)的module。如果你理解這個(gè)了,其實(shí)app目錄單獨(dú)作為一個(gè)項(xiàng)目管理也是可以的,,把相應(yīng)的配置文件配上而已,相當(dāng)于主目錄應(yīng)用 android 的gradle plugin (下一點(diǎn)會(huì)說到這個(gè))
gitignore 該文件是源碼管理的配置文件,不在該文講解。
既然gradle 是多 module形式,那么我們來看看 setting.gradle 配置的內(nèi)容
從上面目錄的配置文件內(nèi)容來看,整個(gè)project也算是一個(gè)module,如果改module底下還有module,就可以通過setting.gradle配置進(jìn)來,使得該module底下的gradle,從app module底下可以看出,module最少要含有 build.gradle文件,這個(gè)module的項(xiàng)目編譯文件,該module依賴什么插件對(duì)該目錄進(jìn)行編譯都在此配置,比如android與android-library,其他內(nèi)容可繼承父類的
Gradle 與 IDEA 的關(guān)聯(lián)性
上面介紹了gradle項(xiàng)目的目錄結(jié)構(gòu),以及module的模式,接下來,了解一下IDEA如何與gradle項(xiàng)目關(guān)聯(lián)上來的。
idea的項(xiàng)目,在建立或者導(dǎo)入的時(shí)候,就已經(jīng)確定他是基于什么自動(dòng)構(gòu)建工具的項(xiàng)目。新建的時(shí)候,使用 gradle androiw module 說明他是 gradle 自動(dòng)構(gòu)建的項(xiàng)目,那么導(dǎo)入的時(shí)候也是一樣。我們看看下面的項(xiàng)目導(dǎo)入圖,在選擇項(xiàng)目地址之后,我們看到一下的內(nèi)容。
如果你的項(xiàng)目里面包含了gradle的相關(guān)文件,就可以選擇 import project form external model 導(dǎo)入IDEA了,如果項(xiàng)目只有源碼,沒有包含自動(dòng)構(gòu)建的相關(guān)信息,你只能選擇 Create project form existing sources 了,讓他生成自動(dòng)構(gòu)建工具需要的文件。
你可能會(huì)想,想gradle里面的依賴包,我不知道有哪些,怎么辦。好吧,你私下里就罵罵作者吧,上傳了源碼不上傳自動(dòng)構(gòu)建相關(guān)的文件,導(dǎo)致項(xiàng)目依賴不完整,還得找資料自己完善,所以這里也希望廣大開源代碼愛好者,在分享你的作品的時(shí)候,希望能夠分享完整的項(xiàng)目信息,別只有源碼,讓人跑不起來項(xiàng)目(牢騷說多了)。
那么下一步是什么呢:
恩,是不是似曾相識(shí)?你沒看錯(cuò),在新建項(xiàng)目的時(shí)候也有這個(gè)選擇,這個(gè)是選擇自動(dòng)編譯的工具的方式。
如果你到官方下載 gradle 綠色包,解壓到某個(gè)目錄,你可以使用 gradle distribution,并設(shè)定 Gradle home 目錄,這樣 IDEA 構(gòu)建編譯項(xiàng)目的時(shí)候,就使用你設(shè)定的gradle版本進(jìn)行。
說到這里,我覺得該說說 use default gradle wrapper 記得新建項(xiàng)目的時(shí)候也是使用 use default gradle warpper,這時(shí)候,上面目錄說到的三個(gè)文件。
gradle/ gradlew gradlew.bat
如果使用這種方法,IDEA會(huì)調(diào)用項(xiàng)目根目錄 gradlew 或者 gradlew.bat (根據(jù)linux,windows,osx自動(dòng)選型)代替原生的 gradle 方法做自動(dòng)構(gòu)建。
這兩個(gè)文件做了什么事情呢:
解析 gradle/wrapper/gradle-wrapper.properties 文件,獲取項(xiàng)目需要的 gradle 版本下載地址 判斷本地用戶目錄下的 ./gradle 目錄下是否存在該版本,不存在該版本,走第3點(diǎn),存在走第4點(diǎn) 下載 gradle-wrapper.properties 指定版本,并解壓到用戶目錄的下 ./gradle 文件下 利用 ./gradle 目錄下對(duì)應(yīng)的版本的 gradle 進(jìn)行相應(yīng)自動(dòng)編譯操作
看了上面的原理,應(yīng)該明白了,如果你自己下載 gradle 讓idea 導(dǎo)入項(xiàng)目的時(shí)候使用。那么其他人就不知道你使用什么版本的gradle版本進(jìn)行自動(dòng)編譯,如果使用 項(xiàng)目目錄自帶的 gradlew 的話,gradlew 就會(huì)自動(dòng)完善 gradle 的安裝,若需要更新 gradle 的版本,只需要修改 gradle/wrapper/gradle-wrapper.properties 文件內(nèi)的下載鏈接即可。而且gradlew的版本和 android 版本是需要適配的,在自己電腦維護(hù)需求不同版本的 gradlew 也是一個(gè)麻煩的事情。
而且這樣的好處也有一個(gè),當(dāng)你在新電腦上下載你的源碼進(jìn)行編譯時(shí),你完全可以不依賴IDE開發(fā)工具,直接在項(xiàng)目目錄下使用 ./gradlew build 即可對(duì)源碼進(jìn)行編譯,因?yàn)樗鼤?huì)自動(dòng)下載 gradle 進(jìn)行調(diào)用,可以使得新電腦較快完成項(xiàng)目開發(fā)環(huán)境適配(對(duì)網(wǎng)絡(luò)依賴較強(qiáng),希望帶上vpn,這就是為什么你們?cè)谛陆?xiàng)目時(shí)需要去下載gradle,還比較慢的原因,我們一起來f-u-c-k-g-f-w)
當(dāng)然,導(dǎo)入項(xiàng)目需要能夠選上use default gradle wrapper的前提是存在上面一個(gè)gradle文件夾與gradlew、gradew.bat
既然可以選擇使用 gradlew 來管理 gradle 或者手動(dòng)指定 gradle 工具,那么已經(jīng)存在的項(xiàng)目如何更改?
這個(gè)問題,我曾在 idea 13 版本上有找到,但是在 idea 14 上面沒找到相應(yīng)的變更設(shè)置。誰要是找到了,記得留言告知我一聲。
在導(dǎo)入項(xiàng)目或者新建項(xiàng)目的時(shí)候,idea 會(huì)根據(jù) build.gradle 文件更新 *.iml 項(xiàng)目文件,有時(shí)候,你會(huì)發(fā)現(xiàn),新增一個(gè)jar包,但是無法讀取jar包內(nèi)容,因?yàn)閷?duì)于 gradle 來說,jar包屬于項(xiàng)目外依賴,包括maven拓展包,都是屬于項(xiàng)目外依賴,需要修改build.gradle 文件,當(dāng)你加入新的 jar包,或者添加了 maven支持包,在idea上面都會(huì)提示需要進(jìn)行同步
恩,上圖你看到的,是我模擬添加一個(gè)jar包之后,隨便加了一個(gè)空格,文件上提示需要進(jìn)行 gradle 項(xiàng)目與 idea項(xiàng)目文件同步,點(diǎn)擊 sync now 之后,idea 會(huì)根據(jù) gradle 文件重新更新 .idea 目錄以及 *.iml 文件,讓idea 可以識(shí)別引入的 資源。
這也就是為什么有人說加入一個(gè)jar包確沒有自動(dòng)提示,而重新打開idea之后就能夠提示使用jar內(nèi)的方法了,因?yàn)橹匦麓蜷_idea,開發(fā)工具會(huì)重新同步 build.gradle 的內(nèi)容
Gradle Android Plugin Version與 Gradle Version對(duì)應(yīng)
gradle只是一個(gè)自動(dòng)化編譯工具,它需要以來插件來識(shí)別這是什么項(xiàng)目,用什么方式去編譯的。我們來看看 build.gradle 與 app/build.gradle 的設(shè)置看看。
不知道你們會(huì)不會(huì)奇怪,在app里面的 build.gradle 中,缺少了 buildscript 與 allproject 的設(shè)置,恩,沒錯(cuò),我刪掉了,因?yàn)檫@個(gè)設(shè)置是可以繼承父項(xiàng)目的 build.gradle
其中父類的整個(gè)項(xiàng)目需要依賴插件 com.android.tools.build:gradle:0.14.2 最后是版本號(hào)。(目前AS的版本號(hào)已經(jīng)是1.0.0了)
這個(gè)插件的版本號(hào)與gradle調(diào)用編譯時(shí)是有依賴關(guān)系的,插件的版本越高,需要更多gradle的新特性,新的gradle特新就需要新版本的gradle才能支持。
這時(shí)候,回到上一節(jié)的內(nèi)容,如果要使用android項(xiàng)目自動(dòng)編譯的新特性,如果選擇不同的gradle指向方式,那么你就要做不同的處理
下載不同版本的gradle對(duì)不同的項(xiàng)目的不同版本做插件與gradle的對(duì)應(yīng)維護(hù),如果其他人使用你的項(xiàng)目,你還要告知他使用什么版本以上的gradle才能使用這個(gè)插件。 把對(duì)應(yīng)關(guān)系一次弄好之后,更新gradle/wrapper/gradle-wrapper.properties下載地址,利用gradlew自動(dòng)使用相應(yīng)版本的gradle,這樣gradlew版本的需求就跟著源碼管理一直保留到其他人的電腦商。
具體的插件依賴,可點(diǎn)擊這里
目錄格式
先來看看eclipse的完整目錄與IDEA的完整目錄結(jié)構(gòu)(當(dāng)然,IDEA看的目錄時(shí)基于module的目錄設(shè)置的,而不是根據(jù)總項(xiàng)目的目錄設(shè)置的)
eclipse目錄
IDEA(AS)目錄
按照Android開發(fā)的目錄,區(qū)分為以下的目錄格式:
代碼根目錄 / src/main adil文件 /src [代碼根目錄]/aidl java文件 /src [代碼根目錄]/java assets文件 /assets [代碼根目錄]/assets jni文件 /jni [代碼根目錄]/jni jnilibs文件 /libs [代碼根目錄]/jniLibs res文件 /res [代碼根目錄]/res AndroidMainfest.xml AndroidMainfest.xml [代碼根目錄]/AndroidMainfest.xml
上面所展示的內(nèi)容就是目前Android用到的所有資源文件類型。為什么要把項(xiàng)目根目錄列出來?這個(gè)到后面渠道包的時(shí)候需要用到??墒且部赡芤矔?huì)問到,為什么項(xiàng)目根目錄會(huì)有兩級(jí)。src 第一級(jí)我的理解是項(xiàng)目源碼相關(guān)都在這里,第二級(jí),認(rèn)為是主項(xiàng)目源碼在 main 目錄,根據(jù)系統(tǒng)完善性,應(yīng)該針對(duì)主項(xiàng)目添加測(cè)試項(xiàng)目的源碼,所以新的代碼里面在 main 目錄同級(jí)的地方會(huì)有 tests 目錄,用于測(cè)試項(xiàng)目的目錄源碼維護(hù)。如果有渠道,還可以為渠道包新建項(xiàng)目目錄去坐項(xiàng)目自定義。
12341. 其中adil是跨進(jìn)程通信使用的2. jni文件夾是存放dnk編譯的c或者cpp文件3. jnilibs文件,就是平時(shí)jni接入使用的 *.so庫。需要里面是需要包含平臺(tái)文件夾的。入下圖所示
當(dāng)我們要從eclipse里面轉(zhuǎn)移到as的時(shí)候,是可以通過gradle來從新定義以上路徑的。在module/build.gradle文件里面有這么一段設(shè)置默認(rèn)設(shè)置,如果按照缺省,可以不寫。
1 2 3 4 5 6 7 8 9 10 11 12 13 sourceSets { main.setRoot('src/main') main { manifest.srcFile '[mainRoot]/AndroidManifest.xml' java.srcDirs = ['[mainRoot]/java'] resources.srcDirs = ['[mainRoot]/java'] aidl.srcDirs = ['[mainRoot]/aidl'] res.srcDirs = ['[mainRoot]/res'] assets.srcDirs = ['[mainRoot]/assets'] jni.srcDirs=['[mainRoot]/jni'] jniLibs.srcDirs = ['[mainRoot]/jniLibs'] }
所示需要適應(yīng)eclipse的目錄格式,可以寫成:
12345678910111213sourceSets {//main.setRoot('src/main')因?yàn)橄旅娴穆窂饺勘欢x了,所以這個(gè)方法已經(jīng)不起作用了。main {manifest.srcFile 'AndroidManifest.xml'java.srcDirs = ['src']resources.srcDirs = ['src']aidl.srcDirs = ['src']res.srcDirs = ['res']assets.srcDirs = ['assets']jni.srcDirs=['jni']jniLibs.srcDirs = ['libs']}
你一定奇怪,為什么libs 的jar包沒有目錄呢?沒錯(cuò),還記得我上面寫過的,對(duì)于 gradle android 項(xiàng)目來說,jar包和library支持,屬于android項(xiàng)目的外部支持,通通由 Gradle 配置文件去管理。上圖的最后一段說明這一切。
Jar支持、Library支持、倉(cāng)庫插件
說到 library ,不得不說說項(xiàng)目類型。
在項(xiàng)目根目錄,我們引入了 android 插件:com.android.tools.build:gradle:0.14.2
我們具體看上圖 build.gradle 的第一行代碼:
1 2 apply plugin: 'com.android.library'
這是說明這個(gè) module 項(xiàng)目說明 android-library 項(xiàng)目,我看過其他的項(xiàng)目,gradle module 是可以依賴多個(gè) plugin 讓這個(gè)項(xiàng)目成為多種類型的項(xiàng)目。
如果是一個(gè)普通android項(xiàng)目,會(huì)是這樣的代碼:
12apply plugin: 'com.android.applition'<p style="border: 0px; font-family: Lato, sans-serif; font-size: 16px; margin-top: 0px; margin-bottom: 24px; outline: 0px; padding-top: 0px; padding-bottom: 0px; vertical-align: baseline; color: rgb(43,
目錄文件 | 作用 | |
---|---|---|
目錄類型 | ECLIPSE | IDEA(ANDROID STUDIO) |