目錄
1、前言
2、咱們須要解決的問題
一、所要達到的效果
二、須要解決的問題
3、編碼時刻
4、效果演示
5、寫在最後
php
通過前幾篇 安卓gradle 文章的介紹,童鞋們應該對 安卓gradle 更加熟悉了。java
一、defaultConfig——安卓gradleandroid
二、buildTypes——安卓gradlegit
三、flavorDimensions和productFlavors——安卓gradlegithub
這幾篇文章中,咱們或多或少的提到 「渠道包」 和 「風味包」 ,今天咱們就來分享下,如何機遇一套代碼,編譯出多個 「能夠並存」 且 「存在有些許差別」 的apk包。微信
完整代碼:github傳送,若是對你有幫助,給個star吧。app
咱們先理清楚作這件事情所要達到的效果 和 中間存在的問題。ide
根據咱們須要想要達到的效果,咱們須要解決如下幾個問題post
接下來咱們就來解決這些問題,達到咱們預期的效果gradle
對 維度 和 風味 陌生的童鞋,能夠移步查看小盆友的另外一片博文:flavorDimensions和productFlavors——安卓gradle
咱們進入應用級的 build.gradle
中,增長如下代碼
android {
// 省略其餘代碼...
// 建立風味維度
flavorDimensions('abi')
productFlavors {
x86 {
// 建立維度
dimension 'abi'
}
armV7 {
dimension 'abi'
}
}
}
複製代碼
至此,咱們能夠編譯出兩個apk包:「x86」 和 「armV7」。從編譯器的提示,咱們也能夠看出已經有 四種變體。
由於 「x86」 和 「armV7」 兩個風味各自都默認有 「release」 和 「debug」 兩種編譯類型,因此 2x2 則有 四種變體。
咱們須要給他們各自定一個 applicationId ,這樣才能夠並存不衝突。
android {
// 省略其餘代碼...
// 建立風味維度
flavorDimensions('abi')
productFlavors {
x86 {
// 建立維度
dimension 'abi'
// 配置 風味的applicationId
applicationId 'com.zinc.bear'
}
armV7 {
dimension 'abi'
applicationId 'com.zinc.shark'
}
}
}
複製代碼
這樣第一個問題解決了!!😊很簡單吧,繼續前行。 但此時運行起來,是兩個徹底相同的apk,還沒進行差別化的配置。
經過使用 manifestPlaceholders 達到這一效果
首先仍是在 build.gradle
中添加如下代碼
productFlavors {
x86 {
dimension 'abi'
applicationId 'com.zinc.bear'
manifestPlaceholders = [
hostName: "www.x86.com",
logo : "@drawable/logo",
appName : "bear",
]
}
armV7 {
dimension 'abi'
applicationId 'com.zinc.shark'
manifestPlaceholders = [
hostName: "www.armv7.com",
logo : "@drawable/logo",
appName : "shark",
]
}
}
複製代碼
接着咱們進入 AndroidManifest.xml 中,進行替換 logo 和 app名字,還有設置了一個 meta-data
的參數。
咱們在 AndroidManifest.xml 中使用 manifestPlaceholders 的參數規則爲 ${參數名字}
,具體完整代碼以下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zinc.flavordemo">
<application android:allowBackup="true" android:icon="${logo}" android:label="${appName}" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="host" android:value="${hostName}"/>
</application>
</manifest>
複製代碼
咱們選擇 「Merged Manifest」(此時爲 armV7Debug 變體),能夠看到 Android Studio 已經將咱們設置的參數替換爲真實的參數。
至此, 咱們解決了第二個問題 「可以動態的設置 AndroidManifest.xml 中的數據」。不一樣的apk,固然會出現 同個地方,使用一樣的資源名,但又要表現不一樣(emmm,很繞😂),咱們舉個例子,細心的童鞋會發現咱們 logo 的資源名是同樣的,咱們接下來看看如何配置。
這裏的 配置有兩種方法 ,小盆友就自做主張的起兩個名字: 「文件夾配置」、「Library 配置」。咱們接下來一一展現。
(1)咱們在跟 main 同級 的地方創建和 風味同樣名字 的文件夾,這裏使用 "armV7" 做爲例子,則命名爲 armV7。而後按照和 main 文件夾一樣的格式創建結構,具體以下圖。
(2)最後將咱們的 logo.png 圖片放入 drawable 中便可。 在編譯包時,會將armV7 文件夾中的資源覆蓋在 main 中同名的資源。(3)這種方式也一樣適用於其餘資源。例如:此處咱們也一樣創建了 strings.xml 文件,其中也寫入 app_name
的 string資源,最終編譯 armv7 時,造成的 app_name
則會爲 flavor_armv7。
armV7 下的 strings.xml 資源
main 下的 strings.xml 資源(1)建立一個library,名稱沒有規定,這裏取名爲 「flavor_x86」。
(2)在 drawable 一樣放入 logo.png 的圖片,結構以下。 (3)最後在咱們項目級的 build.gradle 中加入以下代碼,將其引入。注意此處不是使用 implementation, 而是使用 [風味名稱]+Implementation,這樣引入的 library 只會做用於該風味,例如此處只會做用於 x86 風味。dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// ...其餘引入
// 爲風味 x86 引入 library flavor_x86
x86Implementation project(':flavor_x86')
}
複製代碼
(4)其餘資源也一樣適用,和 「文件夾配置」 的第三小點是同樣的,就不贅述了。
小盆友我的比較喜歡 「Library 配置」 的方法,在真實的項目中也是使用這方案。
主要考慮到以下兩點:
[風味名]Implementation
所引入的 Library。聰明的童鞋其實已經發現,咱們在第三小點中,有存在一個 「java」 的文件夾,咱們只須要保持每一個風味都存在相同的類便可(類路徑要徹底同樣,這樣切換不一樣的風味包都不須要任何更換邏輯)。
咱們須要在不一樣的風味包中調用以下代碼,但又要避免污染核心代碼。
// armv7 風味包
public class LogicUtils {
public static String calculate(int a, int b) {
return "armv7:" + (a + b);
}
}
// x86 風味包
public class LogicUtils {
public static String calculate(int a, int b) {
return "x86:" + (a + b);
}
}
複製代碼
使用方法
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvContent = findViewById(R.id.tv_content);
tvContent.setText("LogicUtils:" + LogicUtils.calculate(1, 2));
}
}
複製代碼
項目結構
至此,咱們第四個問題就解決了。完整代碼:github傳送,若是對你有幫助,給個star吧。
若是喜歡的話請給我一個贊,並關注我吧。文章中若有寫的不妥的地方,請評論區或加我微信與我討論吧,共同進步。
歡迎加我微信,進行更多的交流
若是以爲文章有很大的幫助,快來讚揚一次吧😄