使用Gradle自動化構建多型別apk包
對於多種型別的apk包構建,通常有以下需求:
- 各版本有不同的程式碼、資源
- 上述程式碼中各版本有不同的依賴
- 各版本有不同的Manifest中元素需求
- 各版本有不同的proGuard
Android Studio中使用Gradle編譯多種apk包需要靠productFlavors或者buildTypes實現,如果有兩種product flavor和兩種build type,則他們可以生成2*2=4種不同型別的apk包。下文主要使用productFlavors自定義apk內容,而buildTypes使用預設配置用於處理debug版本和release版本。
以下依次來看這4點怎樣實現
一、不同的程式碼和資源
要實現build時使用不同的程式碼和資源:
- 在build檔案中定義productFlavors
- 為每個Flavor建立對應的資料夾
- 將每個Flavor特有的檔案放入資料夾
... android { ... defaultConfig { ... } signingConfigs { ... } buildTypes { ... } productFlavors { demo { applicationId "com.buildsystemexample.app.demo" versionName "1.0-demo" } full { applicationId "com.buildsystemexample.app.full" versionName "1.0-full" } } } ...
其中defaultConfig{}中為預設值,productFlavors{}會複寫所有可以複寫的值。
2.為每個Flavor建立對應的資料夾
在上面兩個Flavor的基礎上,假設你想在每個Flavor使用不同的SecondActivity檔案,按照下面的步驟:
- 展開app目錄
- 右擊src目錄,選擇New>Directory
- 輸入Flavor的名字,也就是demo,新建
- 在demo中建立以下資料夾 app/src/demo/java app/src/demo/res app/src/demo/res/layout app/src/demo/res/values 如下圖:
PS:上述過程就是將預設的main下的目錄結構複製過來,想新增其他資源也是同樣的操作
3. 將每個Flavor特有的檔案放入資料夾
向上一步新建的目錄中,先在java目錄下建立對應的package,向其中放入SecondActivity.java和其layout檔案,並在res目錄下新增本Flavor的AndroidManifest.xml檔案。Manifest的merge規則見下文。
另外一種方法是右擊app目錄,選擇新增Activity,在引導介面中最後一項Target Source Set選擇你想新增到的Flavor,Android Studio就會自動為你生成對應的AndroidManifest,不過需要稍加修改。
在新增demo所需檔案後,為了新增full所需檔案和包,需要在Android Studio中將build variants切換為fullDebug,否則Android Studio不會將full下的java目錄識別為原始檔目錄,導致不能新增package。
對於demo和full中對應的相同的檔案,注意要保證包名的相同,否則main中程式碼對於不同部分的引用,會因為有不同包名而失敗。
二、不同的依賴
在build.gradle中,使用Flavor名+Compile來規定特定Flavor所需依賴:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
demoCompile 'com.android.support:design:22.2.0'
fullCompile 'com.jakewharton:butterknife:6.1.0'
}
三、不同的Manifest需求
Manifest可以通過Merge的方式合併多個Manifest源。通常來說,有三種類型manifest檔案需要被merge到最終的結果apk,下面是按照優先權排序:
- productFlavors和buildTypes中所指定的manifest檔案
- 應用主manifest檔案
- 庫manifest檔案
簡單來說,manifest的merge會將每個元素及其子元素的節點和屬性進行合併。
例如:
<activity
android:name=”com.foo.bar.ActivityOne”
android:theme=”@theme1”/>
和
<activity
android:name=”com.foo.bar.ActivityOne”
android:screenOrientation=”landscape/>
合併會成為
<activity
android:name=”com.foo.bar.ActivityOne”
android:theme=”@theme1”
android:screenOrientation=”landscape/>
不過
<activity
android:name=”com.foo.bar.ActivityOne”
android:theme=”@theme1”/>
和
<activity
android:name=”com.foo.bar.ActivityOne”
android:theme=”@theme2”
android:screenOrientation=”landscape/>
合併會產生一個衝突,因為都有theme,而theme的屬性不同。
要了解manifest合併的更高階應用,檢視Manifest Merger
四、不同ProGuard需求
android {
buildTypes {
release {
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
productFlavors {
flavor1 {
}
flavor2 {
proguardFile 'some-other-rules.txt'
}
}
}
Android Studio將使用所有的定義在相應buildTypes和相應productFlavors中的規則檔案。
有兩個預設的規則檔案:
- proguard-android.txt
- proguard-android-optimize.txt 存放在SDK中。可以使用getDefaultProguardFile()來獲得檔案的完整路徑,他們除了優化的開啟是否不同之外都相同。