Gradle Plugin Samples 之 Gradle Build Variants(六)

Gradle Build Variants

本例用於講解如何使用 Gradle 利用一份代碼生成多種 APK 。

本例中, app 文件夾中,除了默認會生成的 main 目錄以及 androidTest 目錄之外,我額外添加了6個目錄,分別是: release 、 debug 、 buildtypesnochange 、 playstore 、 amazonstore 、 productflavorsnochange。同時,我們在 app/build.gradle 中將這 6 個文件夾分不到 buildTypes 和 productFlavors 中。

buildTypes {
release {
    applicationIdSuffix '.release'
    signingConfig signingConfigs.release
    zipAlignEnabled false
}
debug {
    applicationIdSuffix '.debug'
    zipAlignEnabled false
}
buildtypesnochange {
    signingConfig signingConfigs.release
    zipAlignEnabled false
}
}

productFlavors {
playstore {
    applicationId 'cc.bb.aa.gradle_build_variants.playstore'
}
amazonstore {
    applicationId 'cc.bb.aa.gradle_build_variants.amazonstore'
}
productflavorsnochange {}
}


我們通過 gradle build 命令,可以生成 9 種不同的 APK ,見下圖:



這 9 種 APK 的包名不同,圖標不同,應用程序名稱不同,首頁中顯示的內容不同,但是卻來自一份代碼。

設置所有的 buildTypes 的 zipAlignEnabled 爲 false 目的是爲了只生成 unaligned 的 APK ,用於只產生 9 個 APK 。因爲 unaligned 的 APK 是編譯 aligned 的 APK的中間產物,會影響我們最終編譯出的 APK 的個數。

爲 release 和 buildtypesnochange 設置簽名是爲了方便安裝到設備中。
仔細觀察額外添加的這 6 個目錄的結構,可以發現它們的結構和 main 的結構是相同的。但是,它們和 main 中的文件還是有一些區別的:
1. 我在對應的目錄下放置了名稱相同內容卻不同的 ic_launcher.png 圖片。
2. 在 release 、 debug 、 playstore 、 amazonstore 中修改了 strings.xml 的內容,同時刪除了action_settings 字段。
3. 在這 6 個目錄中各自創建了對應的類,release 、 debug、 buildtypesnochange 中創建的類類名和方法名均相同,只是返回結果不同; playstore 、 amazonstore 、 productflavorsnochange 中創建的類類名和方法名均相同,只是返回結果不同。
4. 這6個文件夾的 res 文件中的文件以及文件夾,相對於 main/res 文件夾很多都沒有。

觀察 Android Studio 中 Build Variants 面板,發現 app 的選項列表已經不是默認的 release 和 debug 了。



這些列表是一個 productFlavors 和一個 buildTypes 組裝的結果。

在 Android Studio 的 Gradle Plugin 中,每一個 APK 均是由一個 buildTypes 和一個 productFlavors 組裝而成。

在默認的情況下, buildTypes 有 release 和 debug 兩個分支; productFlavors 沒有。

每一個 module/src 都有一個名稱爲 main 的文件夾。這個文件夾屬於 buildTypes 和 productFlavors 基礎,buildTypes 和 productFlavors 都可以訪問和修改 main 文件夾中的內容。

例如:

debug 類型的 APK 的名稱爲 Debugrelease 類型的 APK 的名稱爲 Release; buildtypesnochange 類型的 APK 的名稱爲 playstore 、 amazonstore 、 productflavorsnochange 中設置的 apname 名稱(分別對應Play 、 Amazon 、 Gradle-Build-Variants 。 buildtypesnochange 和 productflavorsnochange 中沒有設置appname ,則使用了 main 中的 appname)。

debug 類型的 APK 的圖標爲 Drelease 類型的 APK 的圖標爲 R; buildtypesnochange 類型的 APK 的圖標爲playstore 、 amazonstore 、 productflavorsnochange 中設置的 apname 圖標(分別對應圖標 P 、 A 、Android 默認圖標。 buildtypesnochange 和 productflavorsnochange 中均沒有設置 ic_launcher.png ,則使用了 main 中的 ic_launcher.png)。

在類 MainActivity 中,有這麼一段代碼:

TextView textView = (TextView) findViewById(R.id.textview);
textView.append("\nappName = " + getString(R.string.app_name));
textView.append("\nBuildTypesName = " + BuildTypesUtils.getBuildTypesName());
textView.append("\nProductFlavorsName = " + ProductFlavorsUtils.getProductFlavorsName());
textView.append("\npackageName = " + getPackageName());


實際上,在 main 文件夾中,並沒有定義 BuildTypesUtils 類和 ProductFlavorsUtils 類( BuildTypesUtils 類定義在 release 、 debug 、 buildtypesnochange 中; ProductFlavorsUtils 類定義在 playstore 、amazonstore 、 productflavorsnochange 中),但是我們可以使用這些類。

---

當你在 Android Studio 的 Build Variants 面板中切換當前選擇的 Build Variants ,你會發現在 Project 面板中,對應的兩個文件夾的 java 和 res 文件夾的圖標會發生變化(顯示爲資源文件夾圖標的樣式),而 main 文件夾中的這兩個文件夾一直表現爲資源文件夾圖標的樣式。

你在 Build Variants 面板切換 Build Variants ,實際上是在更改當前編譯的分支。當你選擇了一個 Build Variants 後,Android Studio 會編譯改 Build Variants 對應的 buildTypes 和 productFlavors 中的類以及資源文件,重新組裝,形成新的 App 。所謂的重新組裝,簡單理解起來就是,將當前的 Build Variants 對應的buildTypes 文件夾中的內容、當前的 Build Variants 對應的 productFlavors 對應的文件夾中的內容、 main 文件夾中的內容合併到一起,形成一個並集。

合併規則:
  1. 圖片、音頻、 XML 類型的 Drawable 等資源文件,將會進行文件級的覆蓋(本例中的ic_launcher.png)。
  2. 字符串、顏色值、整型等資源以及 AndroidManifest.xml ,將會進行元素級的覆蓋(本例中的 appname 、hello_world)。
  3. 代碼資源,同一個類, buildTypes 、 productFlavors 、 main 中只能存在一次,否則會有類重複的錯誤(這就是爲什麼本例中沒有在 main 中定義 BuildTypesUtils 類和 ProductFlavorsUtils 類)。
  4. 覆蓋等級爲:buildTypes > productFlavors > main (這就是爲什麼 release 類型的 APK 的名稱都是Release ; debug 類型的 APK 的名稱都是 Debug ; buildtypesnochange 類型的 APK 的名稱需要根據productFlavors 來確定)。

轉自:http://ask.android-studio.org/?/article/30
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章