在開發(fā)App時,經(jīng)常需要切換開發(fā)環(huán)境,最常用的就是開發(fā)環(huán)境(測試服務(wù)器)和生產(chǎn)環(huán)境(正式服務(wù)器),更保險的,則會在上線前,會先在預(yù)發(fā)布(生產(chǎn)環(huán)境克隆版)環(huán)境跑一遍。
不同環(huán)境之間,簽名、包名、服務(wù)器地址、應(yīng)用名稱、圖標(biāo)可能都不一樣。手動切換環(huán)境不僅麻煩而且易出錯。
為什么不同的環(huán)境要使用不同的applicationId、應(yīng)用名稱甚至圖標(biāo)呢,如果你遇到測試向你抱怨,在同一臺設(shè)備上反復(fù)安裝卸載app,只是為了切換環(huán)境,有時候自己都搞不清出安裝的是哪個環(huán)境app時,你就會懂的這做多么有用。
這里詳細(xì)講幾種多環(huán)境打包編譯的方式。
一個環(huán)境一個分支
比如master就是開發(fā)分支,preview是預(yù)發(fā)布環(huán)境分支,release是生產(chǎn)環(huán)境分支。
不同分支之間,在上線時只有環(huán)境相關(guān)的代碼或者配置是不一樣的。
假設(shè)我們上線的流程是開發(fā)->測試->預(yù)發(fā)布->生產(chǎn),在測試完成后,將master的改動合并到preview分支上,然后切換到preview分支打包預(yù)發(fā)布環(huán)境的安裝包。通過測試后再合并到release,編譯并上線完成。
需要注意的問題:不同分支之間,在代碼合并時要特別注意不要將環(huán)境配置合并了。
使用gradle配置
打開app/build.gradle文件,找到buildTypes,默認(rèn)有debug和release兩個編譯版本,我們添加了第三種:preview。
使用React Native的同學(xué)請注意:
新增一個buildTypes,如果名字不是releaseXXX或則會debugXXX,jsbundle將不會被打包到apk中。
React Native工程中的app/build.gralde寫在前面的注釋中有這么一段:
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
也就是說,如果我們要引入名為preview的buildTypes,需要加入這么一段:
project.ext.react = [
entryFile: "index.js",
// 添加
bundleInPreview: true
]
在buildTypes和productFlavors中,我們多種方式個性化編譯配置。以下是我經(jīng)常用到的幾種:
- applicationId 可以在buildTypes中指定新的,覆蓋defaultConfig中的設(shè)置
- applicationIdSuffix 給applicationId添加后綴,比如.dev這樣的
- manifestPlaceholders 此處定義的內(nèi)容,可以在清單文件AndroidManifest.xml中使用,比如
android:label="${app_name}" - buildConfigField 定義后可以通過BuildConfig.xxx使用
- resValue 跟在xml中定義的量一樣,注意不要重復(fù)沖突就行,在Java中通過
getResources().getString(R.string.app_name)之類的方式拿到,在xml(如布局)中可以通過@string/app_name引用。 - 可以通過gradle.properties設(shè)置環(huán)境變量,如定義簽名文件
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore,則可以在signingConfig 中使用storeFile file(MYAPP_RELEASE_STORE_FILE)。
下面是示例:
多版本打包
buildTypes {
debug {
// applicationId添加后綴
//比如defaultConfig中設(shè)置的applicationId為com.example.myapp
//編譯debug版本時applicationId將是com.example.myapp.dev
applicationIdSuffix ".dev"
manifestPlaceholders = [
app_name: "myApp-dev",
app_icon: "@drawable/icon_deve"
]
//開發(fā)服務(wù)器地址
buildConfigField "String", "BASE_URL", '"https://dev.example.com/api"'
//開發(fā)環(huán)境 極光推送的AppKey
buildConfigField "String", "JPUSH_APP_KEY", '"xxxxxx"'
signingConfig signingConfigs.debug
}
release {
applicationIdSuffix ".prod"
manifestPlaceholders = [
app_name: "myApp",
app_icon: "@drawable/icon_prod"
]
//生產(chǎn)服務(wù)器地址
buildConfigField "String", "BASE_URL", '"https://prod.example.com/api"'
//生產(chǎn)環(huán)境 極光推送的AppKey
buildConfigField "String", "JPUSH_APP_KEY", '"xxxxxx"'
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
preview {
applicationIdSuffix ".preview"
manifestPlaceholders = [
app_name: "myApp-preview",
app_icon: "@drawable/icon_prod"
]
//預(yù)覽版服務(wù)器地址
buildConfigField "String", "BASE_URL", '"https://preview.example.com/api"'
//預(yù)覽環(huán)境 極光推送的AppKey
buildConfigField "String", "JPUSH_APP_KEY", '"xxxxxx"'
// 子模塊沒有preview時,則會匹配release
matchingFallbacks = ['release']
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
多渠道打包
// 類型維度
flavorDimensions "myapp"
productFlavors {
// 官網(wǎng)下載渠道
official {
//自定義資源,類似在strings.xml中配置的
//Java中使用 getResources().getString(R.string.channel)
//xml中使用 android:text="@string/channel"
resValue "string", "channel", "official"
}
//應(yīng)用寶下載渠道
tencent {
resValue "string", "channel", "tencent_market"
}
}
如果想編譯preview版本的apk,則可以
./gradlew assemblePreview
編譯完成后apk保存在app/build/outputs/apk中,由于我們定義了兩個變體(productFlavors),因此將輸出兩個變體版本的apk,存儲路徑是app/build/outputs/apk/{productFlavor}${buildType},一個channel值為official的官網(wǎng)渠道版本,另一個是值為tencent的應(yīng)用包渠道版本。
如果只想編譯一種變體,可以執(zhí)行
./gradlew assembleOfficialPreview
完結(jié)。