首页
/ Expo Go for Android 发布全流程:从版本号提升到 Play Store 上线的官方指南

Expo Go for Android 发布全流程:从版本号提升到 Play Store 上线的官方指南

2026-09-07 23:58:10作者:史锋燃Gardner

Expo Go 是 Expo 生态中让开发者可以在真机上直接运行 RN 项目的宿主应用(本仓库中对应安卓应用包名为 host.exp.exponent)。本文基于仓库官方发布文档 [guides/Releasing Expo Go for Android.md](https://gitcode.com/GitHub_Trending/ex/expo/blob/568c2fa9cb0aebfb505ee743ff7f6e92299ebe92/guides/Releasing Expo Go for Android.md?utm_source=gitcode_repo_files),结合当前 monorepo 源码与脚本,完整拆解一次 Android 版本发布需要经历的五个阶段:版本号提升 → Play Store 更新日志 → CI 构建与真机测试 → 上传后端供 expo-cli 下载 → 提交 Google Play。读完本文,你将掌握发布一个 Android Expo Go 版本所需的全部文件改动、命令操作、CI 审批节点与源码依据。

注意:原始发布文档撰写于旧版仓库布局,路径指向 /android/app/build.gradle。在当前 monorepo 布局下,Expo Go 的安卓工程实际位于 apps/expo-go/android,本文一律以仓库根目录为基准给出可验证的相对路径。

一次 Android 发布背后的总体流程

Expo Go for Android 的发布以 sdk-XX 的 release 分支为基线,任何一次面向用户的更新都遵循同一套“构建 → 测试 → 上传 → 审批”的流水线。整体链条如下:

  1. 在 Gradle 配置中提升 versionCodeversionName,保证应用商店能识别新版本;
  2. 为 Play Store 添加对应版本码的 changelog 文案;
  3. 由 CI(CircleCI client workflow 中的 client_android job)产出 release APK,发布者下载后做真机冒烟测试;
  4. 审批 client_android_apk_release_approve,由 client_android_apk_release 把构建产物上传到 staging 后端(对应 tools/src/Versions.tsstaging-api.expo.dev),使 expo-cli / expotools 能下载该 APK;验证通过后用 et promote-versions 把版本配置同步到生产环境;
  5. 审批 client_android_approve_google_play job,把同一份构建产物通过 fastlane/Fastfileprod_release lane 提交到 Google Play 生产轨道。

以下逐阶段说明每一步的目的(Why)与具体操作(How)。

第一步:提升 Android 工程版本号

为什么(Why): 每个新版本的 Expo Go 都必须拥有新的 versionName(展示给用户)和更大的 versionCode(Android 判定应用更新的唯一依据),否则应用商店与客户端下载逻辑都无法感知“这是一个新版本”。

怎么做(How): 编辑 Gradle 配置中的版本字段。当前 monorepo 中对应的文件是 apps/expo-go/android/app/build.gradle,关键配置位于 defaultConfig 块:

defaultConfig {
  applicationId 'host.exp.exponent'
  minSdkVersion rootProject.ext.minSdkVersion
  targetSdkVersion rootProject.ext.targetSdkVersion
  versionCode 229
  versionName '56.0.1'
  ...
}
  • versionCode:每次发布必须单调递增的正整数,Play Console 与 adb install 都以它判断是否可覆盖安装;
  • versionName:人类可读的版本串(示例中为 56.0.1),会展示在系统“应用信息”页。

同一文件还能看到 Expo Go 安卓工程的若干工程化细节,可作为发布前排查的参考:

  • 工程通过 flavorDimensions "device" 定义了 mobilequest 两个 productFlavor(见 apps/expo-go/android/app/build.gradle),代码中“Expo Go 不需要在构建期打包 JS,所有变体都作为 debuggableVariants”的注释也说明 release 变体直接嵌入已有的 JS bundle;
  • release 签名依赖 CI 注入的环境变量 ANDROID_KEYSTORE_PATH / ANDROID_KEYSTORE_PASSWORD / ANDROID_KEY_ALIAS / ANDROID_KEY_PASSWORD;若没有发布 keystore(本地构建),Gradle 会回退到 debug key 以便测试(见同文件 build.gradle)。

与版本号紧密相关的是构建产物路径:CI 在工作目录 /root/expo 下编译后,APK 位于 apps/expo-go/android/app/build/outputs/apk/release/app-versioned-release.apk(旧布局时代为 /root/expo/android/app/build/outputs/apk/release/app-versioned-release.apk),后续步骤 3、5 使用的正是这份产物。

第二步:为 Play Store 添加更新日志

为什么(Why): 用户在商店中看到“更新”按钮时,理应有简洁的文案说明为什么要升级,这有助于提升升级率并降低客服成本。

怎么做(How):fastlane/android/metadata/en-US/changelogs 目录下新建以新的 versionCode 命名的纯文本文件 [versionCode].txt。该目录中保留了历次版本的记录(91.txt ~ 173.txt 等),例如 changelogs/173.txt 的内容即为一行:

Add support for Expo SDK 46

即:新 SDK 对应的发布通常写作 “Add support for Expo SDK XX”。

这一文件并非可有可无——fastlane/Fastfile 中的 verify_changelog_exists lane 会直接校验其存在:

private_lane :verify_changelog_exists do |version_code: |
  changelog_path = "android/metadata/en-US/changelogs/#{version_code}.txt"
  UI.user_error!("Missing changelog file at #{changelog_path}") unless File.exist?(changelog_path)
  UI.message("Changelog exists for version code #{version_code}")
end

且该校验传入的 version_code 是通过正则从 apps/expo-go/android/app/build.gradle 读取的:

build_gradle = File.read("../apps/expo-go/android/app/build.gradle")
verify_changelog_exists(version_code: build_gradle.match(/versionCode (\d+)/)[1])

这说明 changelog 的文件名必须与第一步设置的 versionCode 严格一致,否则 fastlane 提交阶段会直接报错中断。同目录下的 title.txtshort_description.txtfull_description.txt 则是商店展示元数据,发布时一并上传。

第三步:测试应用(CI 构建 + 真机冒烟)

为什么(Why): 发布用的 APK 由 CI 负责构建,人工在本地很难复现其签名与打包配置;因此在提交任何渠道之前,需要先对 CI 产物做一轮贴近真实用户的测试。

怎么做(How): 在 release 分支 sdk-XX(所有更新发布的唯一来源分支)上完成步骤 2 的提交后,打开 client_android job,下载其构建产物(APK 见上文的 app-versioned-release.apk),然后按以下顺序在 Android 设备上验证:

# 1. 清除旧版 Expo Go 的全部数据,确保从“全新安装”状态测试
adb shell pm clear host.exp.exponent

# 2. 打开设备的飞行模式(切断网络,验证离线基本可用性)

# 3. 安装下载到的 release APK
adb install {downloaded-apk}

# 4. 打开应用,确认 Home 页能正常加载

官方文档在此明确列出了一个已知问题:飞行模式下图标不会加载(图标资源来自网络),测试时不应将其误判为回归缺陷。随后关闭飞行模式,再完整走一遍联网功能路径,确认应用在正常网络环境下工作无误。

第四步:上传到后端,让网站与 expo-cli 能下载到新 APK

为什么(Why): 大量开发者通过 expo-cli / expotools 把 Expo Go 下载到自己的设备(真机或模拟器)运行项目。新的 APK 必须先上传到 Expo 的 versions 后端(staging 环境),这些客户端才能拉取到新版本下载链接。

怎么做(How):

① CI 审批与自动上传到 staging。 在 CircleCI 的 release 分支上打开 client workflow:client_android 完成后,人工审批 client_android_apk_release_approve job,随后触发 client_android_apk_release,它会把 client_android 产出的 artifact 归档上传到 staging。

② 用 expotools 在设备上验证新上传的 APK。 连接 Android 真机或启动模拟器,执行(et 即仓库 tools 目录中的 expotools 工具):

et client-install -p android

这条命令的实际实现见 tools/src/commands/ClientInstall.ts:它会先探测已连接的设备(多设备时提示“只会安装到第一个找到的设备”),卸载旧版 Expo Go(包名 host.exp.exponent,源码常量见 ClientInstall.ts),然后从 versions API 下载对应 SDK 的 Expo Go 压缩包并安装启动。其中关键的下载地址解析逻辑为:

const tarballKey = `${platform}ClientUrl`;
const downloadUrl = sdkConfiguration[tarballKey];

即安卓取 sdkVersions[SDK].androidClientUrl 字段。命令默认访问 staging 环境(Versions.VersionsApiHost.STAGING),也可通过 --production 切到生产、用 -s, --sdkVersion 指定 SDK 版本(ClientInstall.ts)。这正好用来确认步骤 4 上传到 staging 的版本是否可正常下载、安装、启动。

③ 同步版本配置到生产环境。 当确认无误、准备让版本变化对生产用户生效时执行:

et promote-versions

其完整命令为 promote-versions-to-production(别名 promote-versions-to-prodpromote-versions),实现见 tools/src/commands/PromoteVersionsToProduction.ts。它会拉取 staging 与 production 两份版本配置,用 jsondiffpatch 计算差异并打印,经人工确认后把 staging 的配置整体写入生产(Versions.setVersionsAsync(..., VersionsApiHost.PRODUCTION),写入时依赖环境变量 EXPO_VERSIONS_SECRET,见 tools/src/Versions.ts)。

④ 理解 versions 数据结构。 上面的“上传后端”本质上是在维护一份形如下方的版本 schema(类型定义见 tools/src/Versions.ts):

{
  "sdkVersions": {
    "XX.0.0": {
      "androidClientUrl": "https://.../Exponent-XX.0.0.apk",
      "androidClientVersion": "56.0.1",
      "iosClientUrl": "https://...",
      "iosClientVersion": "..."
    }
  }
}

androidClientUrl 正是 expo-cliet client-install 下载 APK 的地址来源,androidClientVersion 则用于比对版本一致性。fastlane/Fastfile 中的 verify_upload_to_staging lane 就是围绕“staging 上的 androidClientVersion 是否等于本次 versionName”这一校验设计的(当前该 lane 被注释跳过,仅保留占位,见 Fastfile),可从中理解这两者必须对齐的约束。

第五步:提交应用商店(Google Play 生产轨道)

为什么(Why): 从 Play Store 下载 Expo Go 的普通用户需要能平滑升级。Play 审核与发布走独立通道,与第四步的后端上传互不影响。

怎么做(How): 回到下载过 app-release.apk 的那个 client workflow,审批 client_android_approve_google_play job。官方文档给出的经验值是:审批后大约 45 分钟,新版本即可在 Play Store 被检索并下载。

fastlane/Fastfile 可以看到该环节自动化对应的 prod_release lane,其核心动作与前置校验是:

lane :prod_release do
  build_gradle = File.read("../apps/expo-go/android/app/build.gradle")

  verify_changelog_exists(version_code: build_gradle.match(/versionCode (\d+)/)[1])
  verify_upload_to_staging(version_name: build_gradle.match(/versionName '([\d\.]+)'/)[1])

  supply(
    package_name: "host.exp.exponent",
    metadata_path: "./fastlane/android/metadata",
    aab: "./apps/expo-go/android/app/build/outputs/bundle/release/app-release.aab",
    track: "production",
    skip_upload_images: true,
    skip_upload_screenshots: true
  )
end

注意两个关键点:

  • 提交的是 AABapp-release.aab)而非 APK,这是现代 Google Play 的首发格式,由系统按设备生成优化的 APK;
  • 提交前会再次校验“changelog 与版本码匹配”以及“版本已上传 staging”,防止把未经验证的版本直接推向商店。

发布清单速查表

阶段 动作 关键文件 / 命令 验收标准
1. 版本号 提升 versionCode / versionName apps/expo-go/android/app/build.gradle versionCode 严格递增
2. 商店文案 新增 changelog 文件 fastlane/android/metadata/en-US/changelogs/[versionCode].txt 文件名 == versionCode,内容如 “Add support for Expo SDK XX”
3. 构建与测试 下载 CI 产物,真机冒烟 adb shell pm clear host.exp.exponent → 飞行模式 → adb install ... → 打开应用 Home 正常加载(飞行模式下图标不加载为已知问题)
4. 上传后端 审批并自动上传,再本地验证,最后同步生产 审批 client_android_apk_release_approveet client-install -p androidet promote-versions 新 APK 可从 staging 正常安装启动;生产 versions 已更新
5. 上架商店 审批 Play 发布 job 审批 client_android_approve_google_play 约 45 分钟后 Play Store 可下载新版本

整个流程的核心原则可以概括为一句话:同一份 CI 构建产物,先经 staging 后端供开发工具链验证分发,再由 fastlane 校验后提交 Play Store,保证“expo-cli 下载到的版本”与“商店用户更新到的版本”始终是同一份经过测试的 release 构建。如果你想进一步扩展阅读,可以在仓库内查看 tools/README.md(expotools 使用说明)、fastlane/README.md(fastlane 目录结构)以及 [guides/Releasing Expo Go for Android.md](https://gitcode.com/GitHub_Trending/ex/expo/blob/568c2fa9cb0aebfb505ee743ff7f6e92299ebe92/guides/Releasing Expo Go for Android.md?utm_source=gitcode_repo_files)(官方原始文档)。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388