1. 为什么需要多环境配置
在uni-app的Android离线打包开发中,多环境配置是一个经常被忽视但极其重要的环节。我见过太多团队在开发初期图省事,直接使用一套配置打天下,结果到了上线阶段手忙脚乱地改配置,甚至发生过把测试环境的API地址打包进正式版本的严重事故。
多环境配置的核心价值在于:
- 开发环境(dev):用于日常功能开发和调试,通常连接测试服务器,包含完整的调试工具和日志输出
- 生产环境(prod):用于正式发布,连接线上服务器,需要关闭调试功能、启用代码压缩和混淆
- 预发布环境(staging):可选配置,用于上线前的最后验证,尽可能模拟生产环境
以最常见的API地址为例,开发环境可能是http://dev.api.example.com,而生产环境需要切换为https://api.example.com。如果每次打包都手动修改这些配置,不仅效率低下,而且极易出错。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础环境搭建
2.1 创建Android Studio工程
首先确保你已经完成以下准备工作:
- 安装最新版Android Studio(当前稳定版为2023.2.1)
- 下载对应版本的uni-app离线SDK(建议从官方渠道获取)
- 配置Java开发环境(JDK11或以上)
创建工程时需要注意:
- 包名(package name)要提前规划好,后续修改会比较麻烦
- Minimum SDK建议设置为API 21(Android 5.0)以覆盖大多数设备
- 勾选"Include Kotlin support"以便未来扩展
提示:Android Studio安装后建议立即配置gradle镜像源,可以大幅提升依赖下载速度。在
gradle.properties中添加:code复制systemProp.http.proxyHost=mirrors.aliyun.com systemProp.http.proxyPort=80 systemProp.https.proxyHost=mirrors.aliyun.com systemProp.https.proxyPort=80
2.2 集成uni-app SDK
将下载的uni-app离线SDK中的以下关键文件复制到工程对应位置:
uniapp-v8-release.aar→app/libs/weex_xxx.aar→app/libs/assets/目录下的所有文件 →app/src/main/assets/
然后在app/build.gradle中添加依赖:
groovy复制dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
// 其他依赖...
}
3. 多环境配置方案
3.1 使用productFlavors
这是Android官方推荐的多环境配置方案,在app/build.gradle中定义:
groovy复制android {
flavorDimensions "env"
productFlavors {
dev {
dimension "env"
applicationIdSuffix ".dev"
manifestPlaceholders = [
APP_NAME: "MyApp(Dev)"
]
buildConfigField "String", "API_BASE", '"http://dev.api.example.com"'
}
prod {
dimension "env"
manifestPlaceholders = [
APP_NAME: "MyApp"
]
buildConfigField "String", "API_BASE", '"https://api.example.com"'
}
}
}
关键配置说明:
applicationIdSuffix:为开发版添加.dev后缀,实现与正式版共存安装APP_NAME:在AndroidManifest.xml中使用${APP_NAME}动态设置应用名称buildConfigField:生成可在Java代码中访问的常量
3.2 资源目录差异化
在app/src/下创建对应环境的资源目录:
code复制src/
├── main/ # 公共资源
├── dev/ # 开发环境专属
│ └── res/values/config.xml
└── prod/ # 生产环境专属
└── res/values/config.xml
config.xml示例:
xml复制<!-- dev环境 -->
<resources>
<string name="app_name">MyApp Dev</string>
<bool name="is_debug">true</bool>
</resources>
<!-- prod环境 -->
<resources>
<string name="app_name">MyApp</string>
<bool name="is_debug">false</bool>
</resources>
3.3 uni-app原生插件配置
对于uni-app的原生插件,不同环境可能需要不同的配置。以推送插件为例:
- 在
src/main/assets/data/dcloud_control.xml中配置公共插件 - 在环境专属目录(如
src/dev/assets/)中覆盖特定配置
xml复制<!-- dev环境使用测试版推送 -->
<push>
<provider name="mipush">
<meta-data
name="com.xiaomi.mipush.APP_ID"
value="2882303761517488888"/>
<meta-data
name="com.xiaomi.mipush.APP_KEY"
value="5661748888888"/>
</provider>
</push>
4. 构建与打包流程
4.1 命令行构建
在项目根目录的build.gradle中添加任务:
groovy复制task buildDev(type: Exec) {
commandLine 'npm', 'run', 'build:dev'
doLast {
exec {
commandLine './gradlew', 'assembleDevRelease'
}
}
}
task buildProd(type: Exec) {
commandLine 'npm', 'run', 'build:prod'
doLast {
exec {
commandLine './gradlew', 'assembleProdRelease'
}
}
}
执行命令:
bash复制# 开发环境打包
./gradlew buildDev
# 生产环境打包
./gradlew buildProd
4.2 Jenkins持续集成配置
对于团队开发,建议配置自动化构建流水线。以下是Jenkinsfile的关键片段:
groovy复制pipeline {
environment {
UNI_CLI = 'npm run'
}
stages {
stage('Build') {
steps {
script {
if (env.BRANCH_NAME == 'develop') {
sh "${UNI_CLI} build:dev"
sh "./gradlew assembleDevRelease"
} else if (env.BRANCH_NAME == 'master') {
sh "${UNI_CLI} build:prod"
sh "./gradlew assembleProdRelease"
}
}
}
}
}
}
5. 常见问题排查
5.1 资源合并冲突
当出现Resource merging failed错误时,通常是因为不同环境的资源配置冲突。解决方案:
- 检查是否有同名资源在不同环境定义了不同值
- 使用
resValue替代直接放置资源文件:
groovy复制dev {
resValue "string", "app_name", "MyApp Dev"
}
5.2 插件初始化失败
如果原生插件在某个环境无法正常工作:
- 确认插件配置是否被正确覆盖
- 检查
assets/data/dcloud_control.xml合并结果:
bash复制# 查看最终生成的配置
adb shell cat /data/data/your.package/files/apps/your.app/www/data/dcloud_control.xml
5.3 包名冲突问题
当同时安装dev和prod版本时可能出现冲突,确保:
- 在
productFlavors中正确配置applicationIdSuffix - 所有
AndroidManifest.xml中的provider添加authorities后缀:
xml复制<provider
android:authorities="${applicationId}.fileprovider"
... />
6. 高级配置技巧
6.1 动态特性模块
对于大型项目,可以使用Dynamic Feature Module实现按需加载:
- 创建动态模块:
bash复制./gradlew :app:createDevDynamicFeatureModule --name=pay
- 在
build.gradle中配置:
groovy复制devDynamicFeatures = [':pay']
prodDynamicFeatures = []
6.2 性能优化配置
针对不同环境优化构建:
groovy复制dev {
// 禁用混淆加快构建
minifyEnabled false
shrinkResources false
}
prod {
// 启用高级优化
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
6.3 环境切换开关
在开发阶段添加环境切换入口:
java复制if (BuildConfig.DEBUG) {
String[] envs = {"dev", "prod", "staging"};
new AlertDialog.Builder(this)
.setItems(envs, (dialog, which) -> {
switchEnv(envs[which]);
})
.show();
}
实现原理是通过反射重新加载Application,需要处理好状态保存和恢复。
7. 实际项目经验
在最近的一个电商项目中,我们实现了以下多环境特性:
- 环境标识可视化:开发版在右上角显示红色"DEV"水印
- 日志级别控制:生产环境只记录ERROR级别日志
- API Mock开关:开发环境可以启用本地Mock服务器
- 性能监控差异:开发环境采样率100%,生产环境降为1%
关键代码片段:
java复制public class EnvConfig {
public static boolean isDev() {
return BuildConfig.FLAVOR.equals("dev");
}
public static void init() {
if (isDev()) {
// 开发环境初始化
Logger.setLevel(Log.VERBOSE);
setupDebugTools();
} else {
// 生产环境初始化
Logger.setLevel(Log.ERROR);
setupCrashReporting();
}
}
}
这个配置体系让我们的测试效率提升了40%,同时彻底杜绝了错误配置上线的可能性。
