Gradle 之創(chuàng)建 Build Variants

什么是 Gradle

Gradle 是一個(gè)高級(jí)構(gòu)建工具。


Gradle構(gòu)建流程

圖片來(lái)自于 Gradle 官網(wǎng)莹妒,根據(jù)官網(wǎng)介紹,上圖從左往右赶站,依次體現(xiàn)了:Build Anything >> Automate Everything >> Deliver Faster. 據(jù)此,我們可以看到它的主要特點(diǎn):可以構(gòu)建的種類多纺念,自動(dòng)化構(gòu)建過(guò)程贝椿,快速交付。
Android Studio 就是使用了這種工具陷谱,來(lái)完成 APK 的打包過(guò)程烙博。如上面所說(shuō),這個(gè)過(guò)程原本是自動(dòng)化完成的烟逊。自動(dòng)化的東西都是流水線渣窜,我們總會(huì)有一些自己的需求,這時(shí)宪躯,就需要自定義配置這個(gè)過(guò)程图毕。
下面,主要討論下構(gòu)建變體的使用眷唉。

構(gòu)建變體的需求

先來(lái)說(shuō)一下這種需求予颤。
通常,在開發(fā)環(huán)境中冬阳,我們會(huì)使用 debug 版本的應(yīng)用蛤虐;在發(fā)布是時(shí)候使用 release 版本。
在 debug 版本中個(gè)肝陪,我們會(huì)有顯示日志的需求驳庭;在 release 版本中是不需要的,日志是為了方便我們調(diào)試氯窍,而且可能包含一些敏感數(shù)據(jù)饲常。
在 release 版本中,通常我們需要進(jìn)行代碼混淆狼讨,否則贝淤,很容易被別人反編譯,就像是一個(gè)人沒有穿衣服政供,顯然播聪,debug 版本就不需要。
從應(yīng)用功能上來(lái)講布隔,同一個(gè) APP 在發(fā)布的時(shí)候离陶,有時(shí)候會(huì)根據(jù)需要發(fā)布不同的版本,比如在不同的應(yīng)用市場(chǎng)上會(huì)有一些定制衅檀,即使是在同一個(gè)市場(chǎng)上招刨,可能也要提供付費(fèi)版和免費(fèi)版等等。

為了解決上述問(wèn)題哀军,不管是從構(gòu)建方式的角度沉眶,還是應(yīng)用功能差異性的角度構(gòu)建 apk 包打却,我們都需要對(duì)這些版本進(jìn)行管理。Gradle 就提供了這樣一個(gè)途徑沦寂,使得我們可以通過(guò)修改 構(gòu)建配置(文件) 的方式以滿足特定版本的需求学密,然后讓 Gradle 根據(jù)我們的選擇自動(dòng)構(gòu)建我們想要的應(yīng)用淘衙。
當(dāng)然传藏,處理問(wèn)題的方式不止一種,我們也會(huì)有很多替代方案彤守。但是毯侦,明明離終點(diǎn)只差一步,為什么還要翻過(guò)一座大山呢具垫?

什么是構(gòu)建變體

談完需求侈离,下面我們來(lái)講講什么是構(gòu)建變體,它是通過(guò) BuildType 和 BuildFlavor 組合實(shí)現(xiàn)的筝蚕。如下所示卦碾,共產(chǎn)生 6 個(gè)變體。

構(gòu)建變體

所謂 BuildType 和 BuildFlavor起宽,即構(gòu)建類型和構(gòu)建特征(或者叫產(chǎn)品風(fēng)味)洲胖。

BuildType,構(gòu)建類型坯沪,主要針對(duì)開發(fā)生命周期的不同階段進(jìn)行配置绿映。一個(gè)模塊或者項(xiàng)目,默認(rèn)有兩種類型腐晾,release 和 debug叉弦。 debug 類型下 debuggable 屬性是 true,從而使得我們可以打斷點(diǎn)進(jìn)行調(diào)試藻糖。debug 類型在打包的時(shí)候淹冰,會(huì)使用默認(rèn)的自動(dòng)生成的簽名,對(duì)于 release 類型來(lái)說(shuō)巨柒,發(fā)布的時(shí)候需要使用我們自己的密鑰進(jìn)行簽名榄棵。同時(shí),我們還可以在發(fā)布的時(shí)候潘拱,進(jìn)行代碼混淆疹鳄。

signingConfigs {
        release {
            storeFile file("xxxx.jks")
            storePassword "xxxx"
            keyAlias "xxxx"
            keyPassword "xxxx"
        }
    }
buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
        }
        //這是自定義的 buildType,繼承自 debug
        /*jnidebug {
            initWith debug
            applicationIdSuffix ".jnidebug"
            jniDebuggable true
        }*/
    }

BuildFlavor芦岂,構(gòu)建特征瘪弓,主要是用以發(fā)布給用戶不同的應(yīng)用版本。需要注意的是禽最,這里的版本并非是版本號(hào)腺怯,而是功能袱饭。比如,我們上說(shuō)所說(shuō)的免費(fèi)版呛占、付費(fèi)版虑乖。

 flavorDimensions "default"
    productFlavors {
        free {
            dimension "default"
            applicationIdSuffix ".free"
            versionNameSuffix "-free"
            buildConfigField "String", "NAME", "\"免費(fèi)版\""
        }
        paid {
            dimension "default"
            applicationIdSuffix ".paid"
            versionNameSuffix "-paid"
            buildConfigField "String", "NAME", "\"付費(fèi)版\""
        }
        cmpy {
            dimension "default"
            applicationIdSuffix ".cmpy"
            versionNameSuffix "-cmpy"
            buildConfigField "String", "NAME", "\"內(nèi)部使用\""
        }
    }

如何使用構(gòu)建變體

上一節(jié),說(shuō)了什么是構(gòu)建變體晾虑,但是疹味,我們?cè)撛趺词褂靡詽M足我們的需求呢?有兩個(gè)地方帜篇,給我們帶來(lái)了可能性:BuildConfig 和 SourceSet(源集)糙捺。

BuildConfig

也許你已經(jīng)注意到了上面 productFlavor 中的

 buildConfigField "String", "NAME", "\"免費(fèi)版\""

事實(shí)上,對(duì)于每一種變體笙隙,都會(huì)有一個(gè) BuildConfig 與之一一對(duì)應(yīng)洪灯。
我們來(lái)看看構(gòu)建變體 free.debug 的BuildConfig:

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.ygs.test.free.debug";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "free";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0-free";
  // Fields from product flavor: free
  public static final String NAME = "免費(fèi)版";
}

這些字段都是靜態(tài)常量,在項(xiàng)目中竟痰,我們都可以通過(guò) BuildConfig 直接訪問(wèn)签钩。比如,你可以通過(guò) BuildConfig.DEBUG 判斷當(dāng)前版本是否是 debug 版本坏快;可以通過(guò) BuildConfig.FLAVOR 判斷當(dāng)前的 productFlavor铅檩,已決定是否啟用某個(gè)功能。當(dāng)然假消,我們也可以自定義字段柠并,比如:

 buildConfigField "String", "NAME", "\"免費(fèi)版\""

上述這些字段,無(wú)論是自定義的富拗,還是默認(rèn)的臼予,都可以成為我們?cè)陧?xiàng)目中的判斷條件。

選擇相應(yīng)的構(gòu)建變體打包
SourceSet

所以源集啃沪,即代碼和資源的分組粘拾。這可能有點(diǎn)抽象,舉個(gè)栗子创千,src/main 就是一個(gè)源集缰雇。
每個(gè) buildType 可以有一個(gè)源集,每個(gè) buildFlavor 可以有一個(gè)源集追驴,每個(gè) buildVariant 同樣可以有一個(gè)源集械哟。
其中,src/main 這個(gè)源集是所有源集所共有的殿雪,除此之外暇咆,源集之間互斥。

使用源集

如上圖所示,一共有三個(gè)源集:freeDebug爸业、freeRelease其骄、main。
注意扯旷,freeDebug拯爽、freeRelease 實(shí)際上是使用 buildVariant 的構(gòu)建的源集,需要和構(gòu)建變體的名字一樣(當(dāng)然可以通過(guò)配置修改這種默認(rèn)行為)钧忽。
這里有幾點(diǎn)注意事項(xiàng):

  • 對(duì)于 java 文件來(lái)講毯炮,freeDebug 中不能出現(xiàn)和 main 中一樣在同一個(gè)包下類名相同的 java 文件,因?yàn)樗麄冎g是共享關(guān)系惰瓜,相當(dāng)于將 main 中的所有 java 和 freeDebug 合并在一起否副。如果出現(xiàn)兩個(gè)相同名字的 java 文件汉矿,會(huì)報(bào)錯(cuò)崎坊。freeDebug 和 freeRelease 不同,它們所有的資源都是互斥的洲拇,相互不影響奈揍,因?yàn)槲覀冊(cè)跇?gòu)建的時(shí)候,也只能選擇其中一種進(jìn)行構(gòu)建赋续。假設(shè)我們選擇了 freeDebug男翰,那么 freeRelease 就會(huì)被剔除在外。
  • 對(duì)于 res 文件夾下的這些資源文件纽乱,freeDebug 和 freeRelease 這些源集之間同樣是互斥的蛾绎,相互沒有任何影響。但是對(duì)于不同源集和 main之間鸦列,卻存在著資源合并或替換的情況租冠。
    對(duì)于 drawable 及其相關(guān)文件夾下的圖片而言,freeDebug 中的圖片會(huì)直接覆蓋 main 中的同名圖片薯嗤。對(duì)于 layout 文件夾下的布局文件也是這樣顽爹。
    但是,對(duì)于 values 文件夾下的 xml 文件來(lái)說(shuō)骆姐,確是文件內(nèi)容的合并镜粤。比如在源集 main 中的 strings.xml 中
<resources>
<string name="app_name">App</string>
<string name="hello_world">Hello world!</string>
</resources>

在源集 freeDebug 中的 strings.xml 中

<resources>
<string name="app_name">FreeDebug</string>
</resources>

它們合并之后就是

<resources>
<string name="app_name">FreeDebug</string>
<string name="hello_world">Hello world!</string>
</resources>

最后,非常重要的一點(diǎn)玻褪,合并或者替換時(shí)會(huì)遵照優(yōu)先級(jí):
buildVariant > buildType > buildFlavor> main > 庫(kù)依賴項(xiàng)

總結(jié)

通過(guò) Gradle 創(chuàng)建 構(gòu)建變體肉渴,等于說(shuō)給了我們告知 Gradle 選擇哪些 class 哪些資源編譯打包成 apk 的權(quán)利,使我們的版本管理更加靈活带射,方便同规。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市庸诱,隨后出現(xiàn)的幾起案子捻浦,更是在濱河造成了極大的恐慌晤揣,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件朱灿,死亡現(xiàn)場(chǎng)離奇詭異昧识,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)盗扒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門跪楞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人侣灶,你說(shuō)我怎么就攤上這事甸祭。” “怎么了褥影?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵池户,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我凡怎,道長(zhǎng)校焦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任统倒,我火速辦了婚禮寨典,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘房匆。我一直安慰自己耸成,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布浴鸿。 她就那樣靜靜地躺著井氢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赚楚。 梳的紋絲不亂的頭發(fā)上毙沾,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音宠页,去河邊找鬼左胞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛举户,可吹牛的內(nèi)容都是我干的烤宙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼俭嘁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼躺枕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拐云,失蹤者是張志新(化名)和其女友劉穎罢猪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叉瘩,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膳帕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了薇缅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片危彩。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泳桦,靈堂內(nèi)的尸體忽然破棺而出汤徽,到底是詐尸還是另有隱情,我是刑警寧澤灸撰,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布谒府,位于F島的核電站,受9級(jí)特大地震影響梧奢,放射性物質(zhì)發(fā)生泄漏狱掂。R本人自食惡果不足惜演痒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一亲轨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸟顺,春花似錦惦蚊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至欧芽,卻和暖如春莉掂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背千扔。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工憎妙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人曲楚。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓厘唾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親龙誊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抚垃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359