本文開發(fā)環(huán)境:
- Android Studio 3.1.4 Build #AI-173.4907809, built on July 24, 2018
- JRE: 1.8.0_152-release-1024-b02 amd64
- JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
- Windows 10 10.0
一、概述
App開發(fā)過程中,基本都需要多個(gè)環(huán)境寞冯,比如開發(fā)環(huán)境develop,測(cè)試環(huán)境check梭稚,生產(chǎn)環(huán)境product。各個(gè)環(huán)境下絮吵,網(wǎng)絡(luò)請(qǐng)求的url會(huì)有所區(qū)別弧烤,一般我們通過baseUrl進(jìn)行切換。
- 開發(fā)環(huán)境用于程序員開發(fā)和自測(cè)蹬敲;
- 測(cè)試環(huán)境用于測(cè)試人員測(cè)試使用暇昂,環(huán)境配置和生產(chǎn)環(huán)境完全相同;
- 生產(chǎn)環(huán)境即正式環(huán)境粱栖,也就是用戶所使用的環(huán)境话浇。
每個(gè)環(huán)境下,app還可以分為debug版本和release版本闹究。
- debug版本下幔崖,apk無需混淆,可以多一些打印日志的操作渣淤。
- release版本下赏寇,文件混淆,隱藏日志打印价认。
Android Studio中嗅定,多版本/多環(huán)境等需求都可以通過配置gradle文件來解決。
二用踩、實(shí)踐
debug和release版本的區(qū)分通過buildTypes
1. 新建一個(gè)demo工程渠退,AS默認(rèn)生成的gradle只有release版本。
defaultConfig {
applicationId "com.allsunny.packagedemo"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
demo中的默認(rèn)applicationId 為com.allsunny.packagedemo脐彩,我們知道碎乃,在Android系統(tǒng)中,同一個(gè)app只能安裝一個(gè)惠奸,系統(tǒng)就是根據(jù)applicationId來判斷是否為同一個(gè)apk梅誓。我們要想在一臺(tái)手機(jī)中同時(shí)安裝debug和release版本,就要修改applicationId 。
2.我們將其略加修改梗掰,添加混淆和debug版本嵌言。debug版本下增加字段applicationIdSuffix用來修改applicationId
buildTypes {
//調(diào)試版本,無混淆
debug {
//為debug版本的包名添加.debug后綴
applicationIdSuffix ".debug"
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
zipAlignEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
修改完成后及穗,我們可以通過選擇Build Variant來選擇不同的打包環(huán)境和打包版本摧茴,目前只有兩個(gè)版本debug和release。如圖所示:
我們選擇release后編譯打包拥坛。
因?yàn)槲覀儸F(xiàn)在有debug和release兩個(gè)版本蓬蝶,release無法再使用默認(rèn)的簽名文件,所以我們要自己生成一個(gè)jks簽名文件猜惋,release包使用新生成的正式簽名文件來簽名。否則會(huì)報(bào)錯(cuò):
the apk for your currently selected variant(app-release-unsigned.apk)is not signed.
Please specity a signing configuration for this variant(release)
配置簽名文件方案:https://blog.csdn.net/l_lhc/article/details/77963683
配置完成后培愁,AS會(huì)自動(dòng)在release{...}中生成 signingConfig signingConfigs.config著摔。然后就可以正常編譯打包了。至此定续,多版本的配置就完成了谍咆。接下來我們來看多環(huán)境的gradle配置。
環(huán)境的區(qū)分通過productFlavors
productFlavors {
//開發(fā)環(huán)境
develop {
applicationIdSuffix ".dev" //applicationId "com.allsunny.packagedemo.dev"
buildConfigField("int", "ENV_TYPE", "1")
manifestPlaceholders = ["app_name": "開發(fā)環(huán)境", "app_launcher_icon": "@mipmap/ic_launcher_dev"]
}
//生產(chǎn)環(huán)境
product {
buildConfigField("int", "ENV_TYPE", "2")
manifestPlaceholders = ["app_name": "生產(chǎn)環(huán)境", "app_launcher_icon": "@mipmap/ic_launcher"]
}
}
編譯后如果報(bào)如下錯(cuò)誤:
All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
則在android{...}中添加 flavorDimensions "default"
android {
flavorDimensions "default"
......
}
目前demo中只添加了開發(fā)環(huán)境和生產(chǎn)環(huán)境私股,開發(fā)者可以自主添加測(cè)試環(huán)境摹察。我們?cè)赿evelop環(huán)境中增加了applicationIdSuffix ".dev" ,這樣就可以在同一臺(tái)手機(jī)中同時(shí)安裝4個(gè)apk包了倡鲸。分別是:
- 開發(fā)環(huán)境debug版本供嚎,包名com.allsunny.packagedemo.dev.debug
- 開發(fā)環(huán)境release版本,包名com.allsunny.packagedemo.dev
- 生產(chǎn)環(huán)境debug版本峭状,包名com.allsunny.packagedemo.debug
- 生產(chǎn)環(huán)境debug版本克滴,包名com.allsunny.packagedemo
buildConfigField表示在編譯生成的BuildConfig文件當(dāng)中添加字段屬性“ENV_TYPE”,我們可以在代碼當(dāng)中根據(jù)BuildConfig.ENV_TYPE的值來判斷apk是處于開發(fā)環(huán)境(1== BuildConfig.ENV_TYPE)還是生產(chǎn)環(huán)境(2==BuildConfig.ENV_TYPE)优床。
manifestPlaceholders中定義的屬性字段會(huì)替換AndroidManifest當(dāng)中的相關(guān)屬性劝赔,我們目前替換了app名稱和icon。在manifest文件中需做對(duì)應(yīng)修改:
<application
android:allowBackup="true"
android:icon="${app_launcher_icon}"
android:label="${app_name}"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
編譯后在Build Variant中可以看到可以生成4個(gè)apk版本了:
我們?cè)陧撁嬷袑虴NV_TYPE打印出來:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvPackageName = findViewById(R.id.tv_package_name);
tvPackageName.setText("packageName = " + getApplication().getPackageName() + "\n\n"
+ "ENV_TYPE = " + BuildConfig.ENV_TYPE);
}
顯示頁面如圖所示:
至此胆敞,我們就完成了多版本和多環(huán)境的gradle文件配置着帽。
三、注意:
- 網(wǎng)上的第三方推送一般以按包名唯一區(qū)分移层,已上線的app有集成推送模塊的仍翰,要根據(jù)不同包名申請(qǐng)多個(gè)賬號(hào)。防止把測(cè)試的推送信息推送給正式用戶幽钢。
- 微信的分享也是根據(jù)包名來進(jìn)行驗(yàn)證的歉备,所以測(cè)試分享模塊時(shí)候,要將環(huán)境改為生產(chǎn)環(huán)境的release版本匪燕。
- 在代碼中使用到provider的地方蕾羊,也需要根據(jù)包名做對(duì)應(yīng)的修改喧笔,比如:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
Matisse.from(this)
.choose(MimeType.ofImage())
.showSingleMediaType(true)
.countable(false)
.capture(true)
.captureStrategy(new CaptureStrategy(true, mContext.getPackageName() + ".fileprovider"))
.maxSelectable(1)
.thumbnailScale(0.85f)
.imageEngine(new GlideEngine())
.forResult(REQUEST_CODE_CHOOSE);