前言
在 Android 开发中,多环境打包是常见需求(如开发、测试、生产环境),可通过 Gradle 配置实现环境隔离,避免手动修改参数。
以下是常用实现方案:
示例
app/build.gradle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| android { signingConfigs { release { keyAlias RELEASE_KEY_ALIAS keyPassword RELEASE_KEY_PASSWORD storeFile file(RELEASE_STORE_FILE) storePassword RELEASE_STORE_PASSWORD } debug { keyAlias RELEASE_KEY_ALIAS keyPassword RELEASE_KEY_PASSWORD storeFile file(RELEASE_STORE_FILE) storePassword RELEASE_STORE_PASSWORD } }
buildTypes { release { minifyEnabled false shrinkResources false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' multiDexEnabled true zipAlignEnabled true aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false signingConfig signingConfigs.release resValue "bool", "IS_DEBUG", "false" } debug { signingConfig signingConfigs.debug debuggable true resValue "bool", "IS_DEBUG", "true" } }
flavorDimensions "app" productFlavors { xhly { resValue "string", "APP_CODE", "xhly" resValue "bool", "IS_NEW_URL", "true" manifestPlaceholders = [ APP_ICON : "ic_launcher", APP_NAME : "应用名", HOME_DEFAULT: "HOME" ] } } }
|
其中变量如RELEASE_KEY_ALIAS在项目根目录gradle.properties中定义
1 2 3 4
| RELEASE_KEY_PASSWORD=psvmc RELEASE_KEY_ALIAS=psvmc RELEASE_STORE_PASSWORD=psvmc RELEASE_STORE_FILE=psvmc.keystore
|
变量获取
在productFlavors中通过resValue定义资源,覆盖main中的值:
resValue定义的变量
代码中获取
1 2 3
| public static boolean isDebug = MyApp.instance.getResources().getBoolean(R.bool.IS_DEBUG);
public static String appCode = MyApp.instance.getResources().getString(R.bool.APP_CODE);
|
manifestPlaceholders中定义的变量
在AndroidManifest.xml中可以这样获取
1
| <category android:name="android.intent.category.${HOME_DEFAULT}" />
|
和
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <application android:name=".MyApp" android:allowBackup="true" android:icon="@mipmap/${APP_ICON}" android:label="${APP_NAME}" android:largeHeap="true" android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:remove="android:appComponentFactory" tools:targetApi="n"> </application>
|
定义多维度flavorDimensions
配置说明
- 声明维度
在 app/build.gradle 中,通过 flavorDimensions 定义维度名称(顺序会影响变种名称的生成):
1 2 3 4
| android { flavorDimensions "environment", "channel" }
|
如果是单维度则不用通过 dimension 指定所属维度。
- 为每个维度定义具体风味
在 productFlavors 中,为每个维度声明具体的风味值,并通过 dimension 指定所属维度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| productFlavors { dev { dimension "environment" buildConfigField "String", "BASE_URL", "\"https://dev.example.com\"" } test { dimension "environment" buildConfigField "String", "BASE_URL", "\"https://test.example.com\"" } prod { dimension "environment" buildConfigField "String", "BASE_URL", "\"https://prod.example.com\"" }
huawei { dimension "channel" manifestPlaceholders = [CHANNEL_NAME: "huawei"] } xiaomi { dimension "channel" manifestPlaceholders = [CHANNEL_NAME: "xiaomi"] } google { dimension "channel" manifestPlaceholders = [CHANNEL_NAME: "google"] } }
|
- 自动生成的变种组合
Gradle 会根据维度和风味的所有可能组合,生成打包变种(结合 buildTypes 如 debug/release)。
例如:
devHuaweiDebug(开发环境 + 华为渠道 + debug 构建)
testXiaomiRelease(测试环境 + 小米渠道 + release 构建)
prodGoogleRelease(生产环境 + 谷歌渠道 + release 构建)
共3(环境)× 3(渠道)× 2(构建类型)= 18种变种。
默认环境
在 Android 开发调试时,默认生效的环境(产品风味)取决于你的 Gradle 配置和 Android Studio 中选中的「构建变体(Build Variant)」。
核心规则:默认由「当前选中的构建变体」决定
开发调试时(点击 Run 按钮运行 app),生效的环境是 Android Studio 中当前选中的 Build Variant 对应的产品风味(Product Flavor)。
- Build Variant 是「产品风味(Flavor)」+「构建类型(Build Type,如 debug/release)」的组合,例如
devDebug、prodDebug 等。
- 默认情况下,Android Studio 会选中第一个声明的产品风味 + debug 构建类型的组合,但这个「默认选中项」可手动修改。
单维度风味(如仅区分环境)
若配置如下:
1 2 3 4 5 6 7 8 9 10
| flavorDimensions "environment" productFlavors { dev { dimension "environment" } test { dimension "environment" } prod { dimension "environment" } } buildTypes { debug {} release {} }
|
初始默认选中的 Build Variant 是 devDebug,因此调试时默认生效 dev 环境。
多维度风味(如环境 + 渠道)
若配置如下:
1 2 3 4 5 6 7 8 9
| flavorDimensions "environment", "channel" productFlavors { dev { dimension "environment" } prod { dimension "environment" } huawei { dimension "channel" } xiaomi { dimension "channel" } }
|
初始默认选中的 Build Variant 是「第一个环境风味 + 第一个渠道风味 + debug」,即 devHuaweiDebug,因此调试时默认生效 dev 环境 + huawei 渠道。
环境资源文件隔离
如果需要不同环境使用不同的资源(如图片、字符串、Manifest 配置、layout),可通过资源目录隔离实现。
创建环境专属资源目录
在app/src下创建与productFlavors同名的目录,放置对应资源:
有替换资源的时候才需要创建对应文件夹,如果不替换不用创建。
1 2 3 4 5 6 7 8 9 10
| app/ ├─ src/ │ ├─ dev/ // 开发环境资源 │ │ ├─ res/ │ │ │ ├─ drawable/ic_logo.png // 开发环境logo │ │ │ └─ values/strings.xml // 开发环境字符串 │ │ └─ AndroidManifest.xml // 开发环境Manifest(如权限、组件) │ ├─ test/ // 测试环境资源(结构同上) │ ├─ prod/ // 生产环境资源(结构同上) │ └─ main/ // 公共资源(所有环境共享)
|
资源优先级
- 环境专属目录的资源会覆盖
main目录中同名资源。
- 例如:
dev/res/values/strings.xml中的app_name会覆盖main中的同名值。
打包apk名称设置
1 2 3 4 5 6 7
| android { android.applicationVariants.all { variant -> variant.outputs.all { outputFileName = "App-${variant.name}-${variant.versionName}-${variant.versionCode}-${releaseTime()}.apk" } } }
|