Android實(shí)現(xiàn)APP環(huán)境分離(利用Gradle)
一、環(huán)境分離簡(jiǎn)介
每個(gè)App項(xiàng)目,至少都會(huì)有兩個(gè)環(huán)境:測(cè)試環(huán)境和生產(chǎn)環(huán)境。多的甚至有四個(gè)環(huán)境:開發(fā)環(huán)境、測(cè)試環(huán)境、預(yù)生產(chǎn)環(huán)境和生產(chǎn)環(huán)境。開發(fā)人員經(jīng)常需要在環(huán)境之間切換,測(cè)試人員也同樣。經(jīng)常出現(xiàn)測(cè)試人員今天需要測(cè)試環(huán)境的最新版本,叫App開發(fā)人員打包一個(gè)給她,明天需要切換到生產(chǎn)版本,再叫App開發(fā)人員打包一個(gè)生產(chǎn)環(huán)境的給她。我們知道,一個(gè)App,在一臺(tái)手機(jī)上要么只能是測(cè)試環(huán)境的,要么只能是生產(chǎn)環(huán)境的。測(cè)試人員要測(cè)試兩個(gè)環(huán)境,只能不斷替換不同環(huán)境的同個(gè)App,這實(shí)在太麻煩了。為了解決此問(wèn)題,最好的方案就是環(huán)境分離,不同環(huán)境有不同的App。
但對(duì)于Android App來(lái)講,相同包名的apk在同一個(gè)設(shè)備上只能存在一個(gè)。所以我們無(wú)法做到在同一個(gè)設(shè)備上同時(shí)安裝生產(chǎn)環(huán)境和測(cè)試環(huán)境的安裝包,這對(duì)于日常的開發(fā)工作和測(cè)試人員的測(cè)試工作極不方便??偛荒軐⒄麄€(gè)工程復(fù)制一份,再通過(guò)修改包名的方式打包出另一個(gè)apk吧。所以在這種情況下,以往常見(jiàn)的做法就是在app中提供一個(gè)隱形的入口,供內(nèi)部人員切換服務(wù)器地址,然后通過(guò)以下代碼重啟App:
private void restartApp(){
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage(getContext().getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
顯然,這種做法也只是一種緩兵之計(jì),多少還是有些不盡人意。然而,值得慶幸地是,進(jìn)入Android Studio時(shí)代后,Google開始使用引入Gradle構(gòu)建系統(tǒng),applicationId的出現(xiàn)使得環(huán)境分離的問(wèn)題迎刃而解。
二、package 與 applicationId
在使用Eclipse開發(fā)Apk或舊版本的Gradle構(gòu)建系統(tǒng)中,應(yīng)用的包名由AndroidManifest.xml文件中package屬性決定。同時(shí),這個(gè)package還被用來(lái)定義命名被引用的資源類R文件。
但是在新的Android Gradle構(gòu)建系統(tǒng)中,package屬性的兩大作用得到了解藕:applicationId作為應(yīng)用的唯一標(biāo)識(shí)符(包名),用于區(qū)分不同應(yīng)用;package屬性定義資源類R文件,用于引用。
applicationId存在于app/build.gradle文件中的defaultConfig配置下,新建項(xiàng)目時(shí)默認(rèn)使用package屬性值初始化,所以如果沒(méi)有特殊的需求,一般我們不會(huì)在意和修改這個(gè)值:
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
...
所以,要實(shí)現(xiàn)Apk的環(huán)境分離,也就是在同一設(shè)備上安裝同一應(yīng)用的不同版本,從本質(zhì)上我們要修改applicationId的值,構(gòu)建打包出不同包名的apk安裝文件。Gradle構(gòu)建系統(tǒng)提供了兩種方式供開發(fā)人員修改applicationId的值,productFlavors和buildTypes,通過(guò)這兩個(gè)方式我們可以輕松實(shí)現(xiàn)apk的打包定制,或者說(shuō)Build Variants(構(gòu)建變種)。
三、Build Variants
項(xiàng)目的productFlavors和buildTypes配置可以在app/build.gradle代碼文件或者Project Structure上修改,作用是一樣的。
四、productFlavors
項(xiàng)目可以通過(guò)定義多個(gè)不同的productFlavors來(lái)實(shí)現(xiàn)應(yīng)用的不同定制版本,每一個(gè)Flavor與buildTypes配合產(chǎn)出對(duì)應(yīng)的一種輸出類型的apk文件,新建的項(xiàng)目初始化只有一個(gè)默認(rèn)的Flavor:defaultConfig

注意:默認(rèn)的defaultConfig為新建的productFlavors提供基本的配置,也就說(shuō),productFlavors的配置會(huì)覆蓋defaultConfig中相同的屬性,從而實(shí)現(xiàn)產(chǎn)品的不同定制版輸出。對(duì)于環(huán)境分離,這里可以通過(guò)定義新的applicationId屬性來(lái)實(shí)現(xiàn)。
五、buildTypes
默認(rèn)情況下,項(xiàng)目的buildTypes包含debug和release兩個(gè)構(gòu)建版本,其中release版本的執(zhí)行需要手動(dòng)設(shè)置簽名文件。對(duì)于環(huán)境分離,與productFlavors不同的是,buildTypes通過(guò)定義applicationIdSuffix來(lái)實(shí)現(xiàn)的,即添加后綴名:

除了這些可配置的屬性外,productFlavors和buildTypes都會(huì)通過(guò)各自的sourceSet來(lái)提供代碼和資源,默認(rèn)的路徑為:src/flavorName和src/typeName。利用這個(gè)特性,我們可以實(shí)現(xiàn)不同定制版本的apk顯示不同的應(yīng)用名稱和桌面圖標(biāo),以便從設(shè)備上進(jìn)行區(qū)分。
productFlavors和buildTypes配合產(chǎn)出各種格式為“flavorName + typeName”的Build Variants,以打包出不同版本的apk。當(dāng)你沒(méi)有自定義flavors,默認(rèn)的defaultConfig也會(huì)與buildTypes形成對(duì)應(yīng)的Build Variants,只是沒(méi)有名字,所以顯示為debug和release。比如這段配置:
android {
...
productFlavors{
beta{
applicationId 'com.yifeng.mdstudysamples.beta'
}
production{
applicationId 'com.yifeng.mdstudysamples'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix '.debug'
}
}
}
我們配置了beta和production兩種productFlavors,release和debug兩種buildTypes。所以,對(duì)應(yīng)的Build Variants就有四種,分別為:betaDebug、betaRelease、productionDebug和productRelease??梢栽贐uild Variants窗口查看并選擇對(duì)應(yīng)的構(gòu)建類型運(yùn)行應(yīng)用:

注意:前面提到,buildTypes通過(guò)添加后綴的方式修改applicationId(包名)的,換句話說(shuō),就是在productFlavors的基礎(chǔ)上修改包名的。所以,在上面這個(gè)例子中,betaRelease構(gòu)建類型打包出的apk文件的包名是:com.yifeng.mdstudysamples.beta.debug。
五、實(shí)現(xiàn)方式
通過(guò)上面這些介紹,基本上大家能夠知道在Android上如何實(shí)現(xiàn)app的環(huán)境分離了。我們可以選擇使用productFlavors和buildTypes這兩種方式在同一個(gè)設(shè)備上來(lái)安裝同一個(gè)應(yīng)用的不同版本。他們道理上是一樣的,只是相比之下,使用buildTypes不用新建productFlavors,更為方便。這里我就buildTypes為例簡(jiǎn)單描述一下環(huán)境分離的實(shí)現(xiàn)。
1.對(duì)于一個(gè)默認(rèn)productFlavors和buildTypes配置的項(xiàng)目,我們修改debug配置的applicationIdSuffix屬性,設(shè)為".debug"(名字可以隨意設(shè)置),release版本不用變動(dòng)。
android {
...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix '.debug'
}
}
}
有了這一步,已經(jīng)能夠?qū)ebug版本和release的apk安裝在同一個(gè)設(shè)備上了。還可以做到更好,比如修改debug版本的桌面圖標(biāo)、應(yīng)用名稱等,便于區(qū)分。
2.我們?cè)趕rc目錄下新建一個(gè)debug目錄,將main目錄下的res目錄復(fù)制一份到debug目錄下,修改各個(gè)分辨率下的桌面Icon和strings.xml文件中的應(yīng)用名稱,加個(gè)debug標(biāo)識(shí)。目錄結(jié)構(gòu)如圖所示:

在構(gòu)建打包時(shí),debug目錄下的res資源采用疊加的方式合并到main里面去,并替換相同的內(nèi)容,而這個(gè)例子只需要修改桌面Icon和應(yīng)用名稱,所以這里我只復(fù)制了res目錄下的相關(guān)文件,其他文件并未復(fù)制。
3.修改代碼里的服務(wù)器接口地址,選擇對(duì)應(yīng)的Build Variants類型,運(yùn)行即可。其實(shí)也可以在debug和main目錄下的string.xml資源文件中定義服務(wù)器地址,然后在程序的入口處賦值給代碼里的全局靜態(tài)變量。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望能對(duì)大家的學(xué)習(xí)或者工作帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
相關(guān)文章
Android使用WindowManager制作一個(gè)可拖動(dòng)的控件
這篇文章主要為大家詳細(xì)介紹了Android使用WindowManager制作一個(gè)可拖動(dòng)的控件的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-08-08
Android6.0 storage目錄sd卡存儲(chǔ)的路徑創(chuàng)建詳解
這篇文章主要介紹了Android6.0 storage目錄sd卡存儲(chǔ)的路徑創(chuàng)建的相關(guān)資料,需要的朋友可以參考下2017-01-01
Android Studio實(shí)現(xiàn)簡(jiǎn)易進(jìn)制轉(zhuǎn)換計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android Studio實(shí)現(xiàn)簡(jiǎn)易進(jìn)制轉(zhuǎn)換計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
一文詳解?Compose?Navigation?的實(shí)現(xiàn)原理
這篇文章主要介紹了一文詳解?Compose?Navigation的實(shí)現(xiàn)原理,文章通告圍繞主題展開詳細(xì)的相關(guān)內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
flutter 輸入框組件TextField的實(shí)現(xiàn)代碼
這篇文章主要介紹了flutter 輸入框組件TextField的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Android BroadcastReceiver實(shí)現(xiàn)網(wǎng)絡(luò)狀態(tài)實(shí)時(shí)監(jiān)聽(tīng)
這篇文章主要為大家詳細(xì)介紹了Android BroadcastReceiver實(shí)現(xiàn)網(wǎng)絡(luò)狀態(tài)實(shí)時(shí)監(jiān)聽(tīng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05

