用途
该技能把 Expo 应用通过一条命令构建为 Release APK,并验证构建产物。命令示例:npm run build:android:emu -- --variant preview。它不依赖 Android Studio、Metro 或上传密钥,用于在 Android 模拟器上试运行应用并确认实际构建出的内容。
主要能力
- 通过单一脚本
scripts/build/build-android-emu.ts完成构建:先预检所有将运行的 npm 脚本(失败则退出码 2,不构建任何内容),再执行npx expo prebuild --platform android --clean、契约中的 post-prebuild 脚本、Gradle、安装、启动与截图。 - 按进程选择 JDK 17 与 Android SDK:
scripts/android/toolchain.ts将 JDK_MAJOR、ANDROID_API、BUILD_TOOLS_VERSION 固定为与已安装 React Native 版本目录相等的字面量;selectToolchain()通过 release 文件定位 JDK 17,检查 SDK 包,并在子进程环境中设置 JAVA_HOME 与 ANDROID_HOME。 - 变体在整个运行中只导出一次:
variantEnv(variant)设置APP_VARIANT = EXPO_PUBLIC_APP_VARIANT,供 prebuild、expo-constants 的 Gradle 任务与 Metro 使用。 - 构建命令为
./gradlew --no-daemon :app:assembleRelease -PreactNativeArchitectures=<abi>,仅针对模拟器对应的单一 ABI(Apple silicon 为 arm64-v8a,其他为 x86_64)。 - 模拟器为命名为
<prefix>-<purpose>的 AVD,通过本次运行选定的控制台端口启动,并仅以 serial 寻址。 - 全新安装与冷启动后,等待就绪信号(进程存活、activity resumed、崩溃缓冲为空、契约的 readyLog 行或至少 3 秒后两张相同截图),再检查并查看截图。
check-apk读取 APK 验证:内嵌 Hermes bundle、仅测试哨兵(development 与 preview 存在,production 不存在)、不可调试、变体自身包名、targetSdk 36 与 minSdk 24 或更高、模拟器 ABI 的原生库且 16 KB 对齐段、签名块,production 无占位符且无明文流量。- 合并后的 manifest 作为权限证据:契约的 permissions 列出应用可携带的每个权限,check-apk 对 APK 中任何其他权限报错。
使用方式
- 首次在仓库中或设置检查失败后,阅读
references/toolchain-and-sdk.md与references/build-variants.md。 - 安装缺失的模板(每个模板第 1 行标明其仓库路径;在契约中填写
__AVD_PREFIX__与__APP_ID__),将templates/scripts/android/下的 toolchain.ts、adb-args.ts、emulators.ts(含测试)放入scripts/android/,将templates/scripts/build/下的 build-android-emu.ts 与 emu-build-*.ts、emu-ready-signal.ts(含测试)放入scripts/build/,将templates/contracts/android-emu-build.json与.schema.json放入contracts/,将templates/src/config/app-variant.ts与测试放入src/config/(已存在则跳过)。 - 在 package.json 添加
"build:android:emu": "node scripts/build/build-android-emu.ts",检查 .gitignore 行,运行npm run typecheck、npx eslint scripts --max-warnings 0、npx jest scripts --ci --maxWorkers=2。 - 运行
node ${CLAUDE_SKILL_DIR}/scripts/check-emu-setup.mjs .,修复每个 FAIL 直到 RESULT: PASS。 - 构建并运行:
npm run build:android:emu -- --variant preview(--help打印选项;--emu <purpose>选择其他 AVD,--link <path>额外截图深链接页面,--keep-emulator保留本次启动的模拟器)。运行会打印 APK 路径与截图路径。 - 验证构建:
node ${CLAUDE_SKILL_DIR}/scripts/check-apk.mjs . --apk build/android-emu/app-preview.apk --variant preview,然后node ${CLAUDE_SKILL_DIR}/scripts/check-emu-screenshot.mjs reports/android-emu/,再打开 PNG 查看。 - 当改动涉及变体、metro.config.js、仅测试代码或构建工具时:在 preview 构建后不清缓存立即运行
--variant production,并对两者运行 check-apk.mjs。 - EAS 或 iOS:EAS APK(
android.buildType: "apk",以--local构建)用同样方式检查,并以adb -s <serial> install安装;iOS 模拟器构建见 ios-simulator-build。 - 任何失败时,对照
references/failures.md匹配文本,修复原因(而非检查),重跑失败步骤,再跑检查。需要安装、许可证或密码的事项应停下询问开发者。 - 用平实语言报告:变体、AVD 名称、profile 与镜像、APK 与截图路径、截图内容、每条 SKIP 行、三条 RESULT 行。结束时按 serial 停止本次会话的模拟器(
adb -s <serial> emu kill)。
适用场景
- 需要在 Android 模拟器上试运行 Expo 应用。
- 需要验证 Release APK 的变体、权限、原生库、签名等实际内容。
- 需要在不使用 Android Studio、Metro 或上传密钥的情况下完成构建与验证。
限制
- 安装 JDK、SDK 包与系统镜像,以及接受 SDK 许可证,属于开发者步骤(许可证是法律协议);代理应停下询问,不得绕过。
- 不得使用
jenv global、sdk default java、update-alternatives或sudo切换 JDK。 - 不得使用
adb -e/-d、adb kill-server、gradlew --stop、Gradle 的 install* 任务、pkill 模拟器或eas build:run -p android。 - 不得通过禁用动画来稳定截图。
- 不得从 BUILD SUCCESSFUL 直接宣告成功,必须安装、启动、截图、检查并查看。
- 生成与输出文件夹(android/、build/、reports/)不进入 git。
- 已验证环境:2026-10-14 使用 Expo SDK 57(expo 57.0.26)、React Native 0.86.3(compileSdk 与 targetSdk 36、build tools 36.0.0、Gradle 9.3.1)、JDK 17.0.11、Android emulator 35.1.20(Apple silicon),启动 API 35 16 KB Play Store 镜像;固定的默认镜像(system-images;android-36;google_apis;<abi>)尚未真实启动过。
- 其他未在资料中说明的功能、收费、价格、平台或效果暂未提供。