Gradle構(gòu)建變種(一份源碼,多份APK)

需求

一份源碼淹魄,修改API地址郁惜,包名,替換桌面圖標(biāo)和一些其他資源文件甲锡,生成不同的APK賣給不同的人兆蕉。

PS 篇幅略長,但是絕對(duì)全是干貨

解決方案

為解決這個(gè)問題缤沦,我經(jīng)歷了以下三個(gè)階段:

1. 需要幾份APK就copy幾份源碼進(jìn)行修改虎韵。
2. 將整個(gè)項(xiàng)目作為module來引用。
3. 使用Gradle的Product Flavors來構(gòu)建變種缸废。

第一種方案:需要幾份APK就copy幾份源碼進(jìn)行修改

這是早期做Android開發(fā)包蓝,仍然是EC橫行的時(shí)候,很痛苦企量,需要幾份就復(fù)制幾份测萎,開始簡單,但是后期維護(hù)
卻是特別的痛苦梁钾。原因是當(dāng)出現(xiàn)一個(gè)BUG的時(shí)候需要修改多次绳泉,雖然說修改完成一份,后面只需要復(fù)制黏貼姆泻,但是也是痛苦零酪,可以想象一下冒嫡,被繁瑣的事情纏繞。

第二種方案:將整個(gè)項(xiàng)目作為module來引用

這是我接觸到了AS四苇,當(dāng)時(shí)考慮的就是將整個(gè)項(xiàng)目改造成為module孝凌,創(chuàng)建不同的主項(xiàng)目來引用同一份源碼,最終改造到一半月腋,不可行蟀架,因?yàn)橐薷拇罅康拇a,比如:
1. ID不再是final類型的了,switch view.id 之類的方法不能再使用榆骚。

第三種方案:使用Gradle的Product Flavors來構(gòu)建變種

前面兩種方案簡直是讓我生不如死片拍,但是隨著時(shí)間的積累,慢慢的發(fā)現(xiàn)出現(xiàn)一種叫做多渠道打包方法妓肢,于是我按照這個(gè)思路找下去捌省,終于在Google的官方文檔中找到了解決方案:

配置構(gòu)建變體

有興趣的小伙伴可以直接去看,里面描述了如何去使用碉钠。

實(shí)踐

1.基礎(chǔ)配置

1.創(chuàng)建一個(gè)普通的空白項(xiàng)目

這一步就不截圖了纲缓,創(chuàng)建就可以了。

2.在manifest中進(jìn)行占位符配置

${APP_ICON} 占位啟動(dòng)圖標(biāo)
${APP_NAME} 占位app名稱

同理喊废,其他第三方需要的相關(guān)配置也是可以使用占位符祝高,例如極光相關(guān)和友盟相關(guān)

    <permission
    android:name="${JPUSH_MESSAGE_VALUE}"
    android:protectionLevel="signature" />
    
     <meta-data
        android:name="UMENG_APPKEY"
        android:value="${UMENG_APPKEY}" />
    <meta-data
        android:name="UMENG_CHANNEL"
        android:value="${UMENG_CHANNEL}" />

以上的占位符,都可以在gradle中使用其它值來替換污筷。

清單文件配置

在Gradle中對(duì)占位符等進(jìn)行配置

  1. 對(duì)defaultConfig節(jié)點(diǎn)做一些修改工闺,增加manifestPlaceholders字段,來替換manifest中的占位符颓屑。為了快速演示斤寂,所以就沒配置極光和友盟了,都是一樣的揪惦。
    defaultConfig {
        applicationId "com.aohanyao.product.flavorsdemos"
        minSdkVersion 18
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [APP_ICON: "@mipmap/ic_launcher",
                                APP_NAME: "這是默認(rèn)的配置"]
    }
    
上面的配置將圖標(biāo)改為了ic_launcher,app的名稱改為了這是默認(rèn)的配置罗侯,為了保險(xiǎn)起見器腋,先直接運(yùn)行APP,看看有沒有更改成功钩杰。

![構(gòu)建默認(rèn)的配置](http://upload-images.jianshu.io/upload_images/1760510-29ff843769d475b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

從上圖可以看到纫塌,已經(jīng)直接運(yùn)行安裝成功了,可以證明我們替換占位符是正確的讲弄。

2.變種的配置措左,ProductFlavors配置
在android節(jié)點(diǎn)中配置productFlavors節(jié)點(diǎn),將defaultConfig節(jié)點(diǎn)復(fù)制一份過來避除,修改一下需要修改的地方怎披,具體如下配置:

productFlavors {
    //變種1
    flavorsdemo1 {
        applicationId "com.aohanyao.product.flavorsdemos.demo1"http://修改了包名
        minSdkVersion 18
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [APP_ICON: "@mipmap/ic_launcher1",
                                APP_NAME: "變種1"]
    }
    //變種2
    flavorsdemo2 {
        applicationId "com.aohanyao.product.flavorsdemos.demo2"http://修改了包名
        minSdkVersion 18
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        manifestPlaceholders = [APP_ICON: "@mipmap/ic_launcher2",
                                APP_NAME: "變種2"]
    }
}

為了方便區(qū)分胸嘁,我增加了ic_launcher1和ic_launcher2兩個(gè)圖標(biāo)。

詳細(xì)配置截圖:

構(gòu)建變種配置

在上面的配置中凉逛,分別修改了APP的包名性宏,名稱以及圖標(biāo)。接下來就是驗(yàn)證是否成功了状飞。只要這這兩個(gè)都能安裝上就算是成功(同樣的包名是不能安裝在同一臺(tái)手機(jī)上的毫胜,當(dāng)然有種黑科技不算)。配置完成后同步一下诬辈。

3.選擇構(gòu)建變體

菜單->Build->Select Build Variant

這時(shí)候左下會(huì)出現(xiàn)一個(gè)窗口酵使,如果Select Build Variant無法選中的話,請(qǐng)先選擇app目錄焙糟。

Select Build Variant

可以看到口渔,在gradle中配置的flavorsdemo1和flavorsdemo2都出現(xiàn)在了了選項(xiàng)中,一個(gè)是debug版本酬荞,一個(gè)是release版本搓劫,不用管它,直接選擇debug版本就好混巧,選擇完成后會(huì)重新創(chuàng)建枪向,這里先選擇flavorsdemo1Debug,等待build完成后直接運(yùn)行咧党。安裝完成后再選擇flavorsdemo2Debug版本秘蛔,等待build,安裝傍衡。見證奇跡的時(shí)候到了:

構(gòu)建變種成功安裝

可以看到深员,變種1和變種2都安裝成功了,而且圖標(biāo)都不一樣蛙埂。這時(shí)候可能會(huì)有人問:包名呢倦畅?來來,使用ADM來看看正在運(yùn)行中的程序:

查看兩個(gè)變種的包名

看绣的,demo1和demo2都在叠赐,而且和我們配置的一毛一樣呀,看到這里屡江,有沒有朋友想到更廣泛的用途呢芭概?

到這里,構(gòu)建變種的基礎(chǔ)就算完成惩嘉,接下來就是配置不同的源碼和資源文件罢洲。

2.源碼配置

業(yè)務(wù)場(chǎng)景

  1. 構(gòu)建多個(gè)APP,那么其中的API的地址肯定是不一樣的對(duì)吧文黎,我的做法是將API存放在一個(gè)全局的常亮類中惹苗,那么久可以將它抽取出來殿较,為不同的變種配置不同的地址。
  2. 權(quán)限控制鸽粉,頁面跳轉(zhuǎn)控制斜脂。說的庸俗一點(diǎn),同一個(gè)APP触机,有一個(gè)功能模塊A是后來開發(fā)的帚戳,而前面有些客戶沒有給這個(gè)功能模塊A的錢,那肯定是不能給他看的呀儡首,所以可以在一個(gè)類中加個(gè)flag來控制顯示與隱藏功能片任。
  3. 反正呢,就是用來配置少量不同源碼蔬胯,大多數(shù)源碼是應(yīng)該寫在main下对供,變種只用來做少量配置。

實(shí)踐

在這我只實(shí)現(xiàn)第一條氛濒,一法通百法通产场,其它都是一樣的。

  1. 首先要使用project視圖舞竿,這樣才能完全的看到整個(gè)項(xiàng)目結(jié)構(gòu)京景,然后在src下(和main同級(jí))創(chuàng)建和變種名字相同的目錄.以下:
構(gòu)建變種,創(chuàng)建源碼目錄
  1. 創(chuàng)建包

首先在flavorsdemo1和flavorsdemo2下創(chuàng)建java和res文件夾骗奖,讓后再java目錄下創(chuàng)建包确徙,這里創(chuàng)建的包要和main下面的一樣,而且flavorsdemo1和flavorsdemo2的目錄也必須一致执桌,還有變種中存在的類鄙皇,main中是不允許存在的。

先看圖仰挣,再解釋:


變種目錄結(jié)構(gòu)

三個(gè)源碼下的包名都是一致的伴逸,在變種中增加了global包,并創(chuàng)建了一個(gè)全局類

flavorsdemo1 Constant

    public class Constant {
    public static final String API_ADDRESS="這是變種1的API地址";
    }

flavorsdemo2 Constant

    public class Constant {
    public static final String API_ADDRESS="這是變種2的API地址";
    }

兩個(gè)類的名字膘壶,變量名稱都是一樣的违柏,只是值不相同,接下來在MainActivity中引用

布局文件


    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.aohanyao.product.flavorsdemos.MainActivity">
    
        <TextView
            android:id="@+id/tv_api"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {

    private TextView tvApi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvApi = (TextView) findViewById(R.id.tv_api);
        tvApi.setText(Constant.API_ADDRESS);
    }
}

直接對(duì)Constant.API_ADDRESS進(jìn)行引用香椎,來,直接啟動(dòng)兩個(gè)變種吧禽篱。

構(gòu)建變種8-源碼配置

圖中分別是flavorsdemo1和flavorsdemo1兩個(gè)變種畜伐,可見,顯示的都是對(duì)應(yīng)的Constant.API_ADDRESS中的值躺率,看到這里玛界,配置不同源碼部分就算是完成万矾,所以應(yīng)該發(fā)散一下思維,這可可以做到很多事情的慎框。

3.資源配置

業(yè)務(wù)場(chǎng)景

比如良狈,變種一和變種二的某個(gè)功能模塊相同,但是名字和圖標(biāo)不相同

1. 大量文字變更
2. 大量圖標(biāo)變更

實(shí)踐

替換字符串資源和圖片資源

首先在兩個(gè)變種的res目錄下創(chuàng)建values目錄笨枯,創(chuàng)建相同的資源文件fd_string.xml薪丁,各自創(chuàng)建相同的字符串資源名稱。并在MainActivity進(jìn)行了引用馅精。

構(gòu)建變種9-配置不同的字符串資源

接下來分別啟動(dòng)兩個(gè)變種严嗜,看看結(jié)果

構(gòu)建變種9-配置不同的字符串資源-結(jié)果

很明顯,達(dá)到了想要的效果洲敢。

下一步就是圖片資源的替換漫玄,和上面一樣,創(chuàng)建相應(yīng)的資源文件夾压彭,放入名稱一樣睦优,內(nèi)容不一樣的圖片,并在MainActivity中引用壮不。

構(gòu)建變種10-圖片資源配置

來看看結(jié)果

構(gòu)建變種10-圖片資源配置-結(jié)果

至此汗盘,利用Gradle構(gòu)建變種就算是完全完成了。

最后

如果文中有什么不對(duì)的地方忆畅,歡迎指出衡未!

源碼地址 歡迎star

我的簡書

來來掃下碼,關(guān)注一下吧,或者微信搜索AndroidRookie

微信公眾號(hào)

AndroidRookie
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末家凯,一起剝皮案震驚了整個(gè)濱河市缓醋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绊诲,老刑警劉巖送粱,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異掂之,居然都是意外死亡抗俄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門世舰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來动雹,“玉大人,你說我怎么就攤上這事跟压∫闰穑” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茸塞。 經(jīng)常有香客問我躲庄,道長,這世上最難降的妖魔是什么钾虐? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任噪窘,我火速辦了婚禮,結(jié)果婚禮上效扫,老公的妹妹穿的比我還像新娘倔监。我一直安慰自己,他們只是感情好荡短,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布丐枉。 她就那樣靜靜地躺著,像睡著了一般掘托。 火紅的嫁衣襯著肌膚如雪瘦锹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天闪盔,我揣著相機(jī)與錄音弯院,去河邊找鬼。 笑死泪掀,一個(gè)胖子當(dāng)著我的面吹牛听绳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播异赫,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼椅挣,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了塔拳?” 一聲冷哼從身側(cè)響起鼠证,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎靠抑,沒想到半個(gè)月后量九,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颂碧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年荠列,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片载城。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肌似,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诉瓦,到底是詐尸還是另有隱情锈嫩,我是刑警寧澤受楼,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站呼寸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏猴贰。R本人自食惡果不足惜对雪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望米绕。 院中可真熱鬧瑟捣,春花似錦、人聲如沸栅干。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碱鳞。三九已至桑李,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窿给,已是汗流浹背贵白。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留崩泡,地道東北人禁荒。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像角撞,于是被迫代替她去往敵國和親呛伴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,826評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,185評(píng)論 25 707
  • 說明 本文主要介紹和Gradle關(guān)系密切谒所、相對(duì)不容易理解的配置热康,偏重概念介紹。部分內(nèi)容是Android特有的(例如...
    jzj1993閱讀 15,635評(píng)論 1 62
  • 那年夏天百炬,紅萼無言 那年夏天褐隆,竹外疏花 那年夏天,此時(shí)寂寂
    九爺kkw閱讀 187評(píng)論 0 0
  • 涂鴉剖踊、勾抹庶弃、以及心理學(xué)領(lǐng)域應(yīng)用廣泛的房樹人心理測(cè)驗(yàn),能夠鮮明形象生動(dòng)的呈現(xiàn)人類的潛意識(shí)德澈,以此來了解自己歇攻,認(rèn)知...
    鶴鶴心理閱讀 682評(píng)論 0 1