天天看點

android之gradle版本差異化打包

對于版本差異化打包,如果實際工作中沒怎麼用到,對這塊一般不會很熟悉,記得在上一家公司的時候,一個主版本公司自己用的,由于公司和其他的公司有合作,其他公司對于app要求定制化,總體上的功能沒怎麼變化,主要的變化還是界面(背景,圖檔還有一些文字之類的),一開始采用的方案是基于主版本建立一個工程,剛開始還沒什麼,但到後面發現問題越來越多了,很不利于維護,工程多了管理起來也很麻煩,不過最開始也是在eclipse上開發,後面接觸到android studio,發現android studio很好的解決了版本差異化打包這個問題,效率提高的不止一點點,比如,之前如果發現bug,在每個版本上都需要修改,但遷移到android studio上後,配置好差異化打包後,隻需更改一個就可以了。接下來就一起來探讨下。

如何實作自己自己的差異化打包,這裡先來了解個需求,有需求才好下手不是。假如一開始有個主版本master,由于後期公司的發展,與xiaomi、huawei、meizhu等有合作了,公司開始要求基于主版本開發與xiaomi、huawei、meizhu的定制化版本,随意業務的發展,xiaomi可能要求在不同的管道要有不同的定制化,既然有這樣的需求,那肯定就是幹呗,需求有了,接下來就是分析該如何下手了,思路有以下三種:

1、每一個定制版本都建立一個工程;

2、每一個定制版本都從主版本上拉一個分支出來;

3、一個工程,通過gradle實作差異化配置;

對于1、2點的方案肯定是不可取,後期的維護成本過大,是以這裡采取的3方案,這裡要說的也是第三個方案,配置起來很簡單,如下配置即可:

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.zzq.variantdemo"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    flavorDimensions 'company','chanel'
    productFlavors {
        master {
            dimension 'company'
        }
        meizhu {
            dimension 'company'
        }
        huawei {
            dimension 'company'
        }
        xiaomi {
            dimension 'company'
        }
        chanelA {
            dimension 'chanel'
        }
        chanelB {
            dimension 'chanel'
        }
    }
}
           

看flavorDimensions和productFlavors這兩個配置,flavorDimensions配置的是次元,productFlavors通過次元再進行細化的配置,這裡以master(主版本)為例,通過productFlavors這樣配置後,這裡master的差異化版本就有masterchannelA和masterchanelB兩個差異化版本,在加上debug和release,是以master的差異化版本就達到4個,以此類推xiaomi、huawei、meizhu,這樣配置後總的差異化版本就達到16個,這裡隻是配置了,但每個版本的差異化還沒有實作,這個實作主要涉及到兩個方面,一是資源檔案,二是代碼的邏輯。

在上面這樣配置完成後,接下來做的就是去src包下面建立檔案夾了,如下圖:

android之gradle版本差異化打包

就是将productFlavors下面配置公司名和管道名都在src包下建立一個檔案夾,然後參照main包下的格式添加java代碼、資源檔案或是AndroidMenifest,這裡添加的就是與主版本有差異化的東西,因為當這裡的資源檔案與main包下的資源檔案有沖突時,這裡添加的資源檔案就會替換掉main包下的資源檔案,但對于java包下的類檔案則不然,當main包下有的類檔案,其他包下就一定是不能有的,說到這可能還不太明白,接下來舉個具體的例子:

如果想打對應的差異化包,如下圖進行選擇:

android之gradle版本差異化打包

所謂差異化打包就是将不同包下面的檔案進行整合,以打的包是masterChanelADebug為例說下這樣配置是如何實作差異化的,下面将分為三個方面來說:

1、java包下的類檔案(這裡所指的是包名和類名全部相同)整合,如果master包下有People.class檔案,那麼在chanelA包下和main包下就不能有,在master包下沒有People.class沒有,在chanelA包下有,那麼在main包下就不能有,以此類推;

2、res包下的資源檔案整合,分為兩種:一是資源檔案沒有沖突,那麼就以添加的方式進行合并,二是如果有沖突,那麼合并的時候就遵循以下優先級:master>chanelA>main

3、AndroidMenifest檔案中配置同樣會整合到一起,同樣分為兩種,一是沒有沖突那就直接合并,二是如果有沖突,預設的合并規則是報異常,是以這時就需要指定合并規則了,如何指定指定合并規則不是這裡的重點, 有沖突時根據提示的異常添加即可,這裡看個簡單的替換規則:

android之gradle版本差異化打包

AndroidMenifest.xml檔案下都有custom_name,這時如果不指定規則,編譯肯定是會有異常的,在master下的AndroidMenifest.xml添加了如下規則:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.zzq.variantdemo">

    <application>
        <meta-data android:name="custom_name"
            android:value="chanel"
            tools:replace="android:value"/>
    </application>

</manifest>
           

可以分為兩步:

1、引入:xmlns:tools="http://schemas.android.com/tools"

2、指定規則:tools:replace="android:value",大多數情況這個就夠用了,如果還有其他需求,也可以添加其他規則,感興趣的可以自行百度。

這裡添加規則也是有優先級的,需在優先級高的添加規則:master>chanelA>main

繼續閱讀