android多渠道包(風味包)——安卓gradle

目錄
1、前言
2、咱們須要解決的問題
一、所要達到的效果
二、須要解決的問題
3、編碼時刻
4、效果演示
5、寫在最後
php

1、前言

通過前幾篇 安卓gradle 文章的介紹,童鞋們應該對 安卓gradle 更加熟悉了。java

一、defaultConfig——安卓gradleandroid

二、buildTypes——安卓gradlegit

三、flavorDimensions和productFlavors——安卓gradlegithub

這幾篇文章中,咱們或多或少的提到 「渠道包」 和 「風味包」 ,今天咱們就來分享下,如何機遇一套代碼,編譯出多個 「能夠並存」 且 「存在有些許差別」 的apk包。微信

完整代碼:github傳送,若是對你有幫助,給個star吧。app

2、咱們須要解決的問題

咱們先理清楚作這件事情所要達到的效果 和 中間存在的問題ide

一、所要達到的效果

  • 一套核心代碼編譯出多個 「能夠並存」 的apk包
  • 能夠有差別化,eg:logo、app名字、簽名、統計渠道 等能夠根據不一樣的apk有些許不一樣
  • 易維護,耦合度低

二、須要解決的問題

根據咱們須要想要達到的效果,咱們須要解決如下幾個問題post

  • 可以配置多個 applicationId
  • 可以動態的設置 AndroidManifest.xml 中的數據
  • 可以使用不一樣的資源,但又不污染核心代碼
  • 可以實現差別化邏輯

接下來咱們就來解決這些問題,達到咱們預期的效果gradle

3、編碼時刻

一、創建 維度 和 風味

對 維度 和 風味 陌生的童鞋,能夠移步查看小盆友的另外一片博文: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,還沒進行差別化的配置。

三、動態的設置 AndroidManifest.xml 中的數據

經過使用 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 配置」。咱們接下來一一展現。

3.1 文件夾配置

(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 資源

3.2 Library 配置

(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)其餘資源也一樣適用,和 「文件夾配置」 的第三小點是同樣的,就不贅述了。

3.3 兩種方法的比較

小盆友我的比較喜歡 「Library 配置」 的方法,在真實的項目中也是使用這方案。

主要考慮到以下兩點:

  • 真正的解耦,由於 「文件夾配置」 這一方案在小盆友看來,其實和 「main」文件夾(核心代碼)仍是有共用一些資源,例如 build.gradle。
  • 易去除,「Library 配置」 方案在移除或更換依賴的 Library 時,很是簡單,只須要更改 [風味名]Implementation 所引入的 Library。

四、可以實現差別化邏輯

聰明的童鞋其實已經發現,咱們在第三小點中,有存在一個 「java」 的文件夾,咱們只須要保持每一個風味都存在相同的類便可(類路徑要徹底同樣,這樣切換不一樣的風味包都不須要任何更換邏輯)。

4.1 代碼時刻

咱們須要在不一樣的風味包中調用以下代碼,但又要避免污染核心代碼。

// 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));
    }
}

複製代碼

項目結構

至此,咱們第四個問題就解決了。

4、效果演示

完整代碼:github傳送,若是對你有幫助,給個star吧。

4.1 運行效果

4.2 並存效果

4.3 兩個應用

5、寫在最後

若是喜歡的話請給我一個贊,並關注我吧。文章中若有寫的不妥的地方,請評論區或加我微信與我討論吧,共同進步。

歡迎加我微信,進行更多的交流

若是以爲文章有很大的幫助,快來讚揚一次吧😄
相關文章
相關標籤/搜索