安卓多环境打包、UAT/生产测试与上架 Google Play 全流程指南
此处省略了一堆业务代码的开发过程...一、多环境架构base_url 必须从配置读取多地区/多环境通常用 Product Flavor 实现。以 dev / uat / sgp / me / eu 五个 flavor 为例FlavorapplicationId说明devcom.example.charge.dev开发联调uatcom.example.charge.uat海外 UAT与 dev 同包名sgpcom.example.charge.sgp生产-新加坡mecom.example.charge.me生产-中东eucom.example.charge.eu生产-欧洲最容易踩的坑运行时 base_url 并不一定来自 BuildConfig.BASE_URL。很多项目实际是在启动时读取 assets/ 下的配置文件如 bff_config.yml顶部的 environment 字段再取对应段的 base_url。BuildConfig 里注入的那个值可能根本没人读。各环境 base_url占位示例Flavorbase_urldevhttps://dev-api.example-charge.comuathttps://uat-api.example-charge.comsgphttps://sgp-api.example-charge.commehttps://me-api.example-charge.comeuhttps://eu-api.example-charge.com排查「环境不对」时先看打包用的 flavor 和对应配置文件不要被 BuildConfig 误导。二、构建与打版1) 可用变体白名单通常只在 androidComponents.beforeVariants 中放开需要的变体例如 devDebug、uatDebug、sgpRelease、meRelease、euDebug、euRelease。android studio2) 常用命令在 mobile/android 根目录执行# UAT 调试包验证功能/环境 ./gradlew :apps:app:assembleUatDebug # 生产 AAB上架 Google Play 用 cd mobile/kotlin ./gradlew :apps:cpms:cpmsApp:clean \ :apps:cpms:cpmsApp:bundleSgpRelease \ :apps:cpms:cpmsApp:bundleMeRelease \ :apps:cpms:cpmsApp:bundleEuRelease # 产物命名类似 app--release--时间戳.aab apps/cpms/cpmsApp/build/outputs/bundle/sgpRelease/app-sgp-release-vc-date.aab apps/cpms/cpmsApp/build/outputs/bundle/meRelease/app-me-release-vc-date.aab apps/cpms/cpmsApp/build/outputs/bundle/euRelease/app-eu-release-vc-date.aab # 生产 Release APK无外网时直装测试用 cd mobile/kotlin ./gradlew :apps:cpms:cpmsApp:clean \ :apps:cpms:cpmsApp:assembleSgpRelease \ :apps:cpms:cpmsApp:assembleMeRelease \ :apps:cpms:cpmsApp:assembleEuRelease # 产物命名类似 app--release--时间戳.apk apps/cpms/cpmsApp/build/outputs/apk/sgp/release/app-sgp-release-*.apk apps/cpms/cpmsApp/build/outputs/apk/me/release/app-me-release-*.apk apps/cpms/cpmsApp/build/outputs/apk/eu/release/app-eu-release-*.apk检查 AAB 的 base_url 配置## cd到aab所在目录 unzip -p cpmsApp-sgp-release.aab base/assets/bff_config.yml bff_config_out.yml more bff_config_out.yml ## cd到apk所在目录,apk可以直接看环境配置 unzip -p ./app-*.apk assets/bff_config.yml3) APK vs AABAPK可直接 adb install 到手机测试。AABGoogle Play 只收 AAB不收 APKPlay 会按用户设备动态生成 APK。4) 版本号与签名占位versionCode 固定基数 git 提交数如 1000 git rev-list --count HEAD保证单调递增。versionName 手动维护如 1.2.1。签名release 用 keystore/release.jksalias release密码从 local.properties 的 KEY_PASSWORD 读取debug 用独立的 keystore/debug.jks。release 开启 minifyEnabled shrinkResources打 bundle 时的 strip 警告属正常不影响产物。三、UAT 测试流程打包assembleUatDebug或 uatRelease。安装注意若 uat 与 dev 共用 applicationId手机上已装 dev 包时必须先卸载再装 uat否则会出现环境/缓存错乱、看起来 base_url 仍是 dev 的地址adb uninstall com.example.charge adb install -r app-uat-debug-*.apk环境验证进入 App确认请求域名是 https://uat-api.example-charge.com可在抓包/日志/关于页核对。功能验收走核心链路如设备添加/绑定确认新改动生效。四、生产测试流程方案 A无外网环境 —— 直装 Release APK 安全验证适用于内网/无法访问 Google Play 的实测场景打对应 flavor 的 release APKassembleXxxRelease不要执行 publish。安装adb install -r app-flavor-release-*.apk。验收用测试账号走完整核心链路。安全注意release APK 含正式签名只限内部测试严禁外发/上传公开渠道测完及时清理设备上的包。方案 B有外网 —— Google Play Internal 轨道实测打 AAB见第二节。上传到 Play Console 的 Internal内部测试 轨道。加入内部测试人员名单下载实测。验收通过后在 Console 从 Internal 晋级到 Production见第五节不重新打包。生产验收清单通用各 flavor 安装后 base_url 正确核心链路登录/绑定/支付/推送走通新老数据兼容如旧格式序列号仍可绑定崩溃率/关键埋点正常多语言、深色模式等基础体验五、上架 Google Play关键点AAB 只需打包一次后续在 Play Console 内从 Internal 晋级 Production 不重新打包Play 启用 App Signing 后上传的 AAB 由 Google 托管签名。# 1) 解密 Play 服务账号密钥依赖 KEY_PASSWORD ./gradlew :apps:app:decryptSecrets # 2) 上传 AAB 到 Internal 轨道 ./gradlew :apps:app:publishSgpRelease ./gradlew :apps:app:publishMeRelease ./gradlew :apps:app:publishEuRelease # 3) Play Console → Internal 轨道实测 # 4) 验证通过后在 Console 将版本从 Internal 晋级到 Production不重新打包 # 5) 清理密钥 ./gradlew :apps:app:cleanSecrets六、经验总结 / 发版 CheckListbase_url 来源要查清楚以运行时实际读取的配置文件为准别被 BuildConfig 误导。同 applicationId 的 flavor 必须先卸载再装如 uat/dev。测试包与上架包同源Play 走 AAB 一次打包 轨道晋级避免「测试用 APK、上架用 AAB 行为不一致」若发版期间未改代码直接复用已打好的 AAB。release 签名安全KEY_PASSWORD、keystore、service-account.json 均为机密只允许本地/CI 使用勿提交明文、勿外发。发版前 CheckList目标 flavor / 变体正确versionCode 单调递增、versionName 正确各环境 base_url 配置正确UAT 已通过、生产实测已通过AAB 已上传 Internal 并晋级 Production密钥/敏感文件已清理