移动/游戏
在任意环境远程构建 Android APK/AAB…
当你想从 Linux、Windows、macOS、VM、容器等任何环境构建原生 Android、React Native 或 Expo 项目,并完成 APK/AAB 构建、签名、上传或 Play 发布时适用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在任意环境远程构建 Android AP特定
解决思路
- 用 Limrun 远程 Gradle 沙箱构建,不要回退到本地 Gradle、本地 Android SDK 或本地模拟器;任务不止于构建成功,要让应用运行或交付工件,并迭代直到用户满意。
- 安装 CLI:`npm install --global lim`。
- 认证:运行 `lim login`,或设置 `LIM_API_KEY`;API key 可能在项目外设置,不要仅因 `.env` 或 shell 中缺失就向用户索要。
- CLI 是事实来源:命令已在此技能中验证,但如果某个 flag 报错或需要未列出的 flag,查看 `lim gradle --help` 和 `lim gradle build --help`,不要猜测。
- 用 `lim gradle build .` 代替 `./gradlew` 构建;它会创建或复用记住的 Gradle 实例,同步当前目录,并默认运行 `assembleDebug`。
- 用 `--task`(可重复)显式选择任务,例如 `lim gradle build . --task :app:assembleRelease`。
- 当 Gradle 根目录嵌套且自动发现不明确时(例如裸 React Native 仓库中 Gradle 位于 `android/`),用 `--project-path`,例如 `lim gradle build . --project-path android`。
- Expo managed-workflow 项目(无 `android/` 目录)会自动检测:沙箱安装依赖并在 Gradle 前运行 `expo prebuild`;设置 `--expo-app-dir`(monorepo)或 `--abi` 会强制该流水线,且检测不到 Expo 应用时报错,例如 `lim gradle build ./my-monorepo --expo-app-dir apps/mobile`。
- 用 `--detach` 让构建被接受后立即返回;webhook 可选。
- 用 `lim gradle logs` 读取最新构建日志,无需 exec ID,包括实例删除后持久化的日志;加 `--follow` 等待完成,例如 `lim gradle logs --follow`。
- 同步后,用 `lim gradle use` 选择沙箱中的工具并安装缺失版本。
- 用 `lim gradle tools install` 安装同步项目中选定的工具。
- 用 `lim gradle tools` 查看工具;Node 包含 npm/npx。
- 用 `lim gradle use node@24 pnpm@10 yarn@4 bun@1 java@temurin-17 bundletool@1` 选择工具版本。
- 用 `lim gradle run -- mise use --pin node@24.5.0` 在沙箱中运行 shell 命令。
- 用 `lim gradle run --env APP_ENV=staging -- npm run generate` 带环境变量运行命令。
- 用 `lim gradle build . --env APP_ENV=staging` 带环境变量构建。
- 将构建的 APK 上传为命名资产:`lim gradle build . --upload myapp.apk`。
- 在 Android 实例上安装资产:`lim android create --install-asset=myapp.apk`。
- 构建上传默认 TTL 为 14 天:每次构建将资产到期时间推至该次上传后 14 天;用 `--upload-ttl` 传 Go duration(例如 `720h`;`1d` 无效)修改。
- 将 create 输出中的签名流 URL 以 Markdown 链接分享给用户,例如 `[Live emulator](<signed-stream-url>)`。
- 重建迭代时,用 `lim android sync ./path/to/app-debug.apk` 就地修补已安装 APK,而不是重建实例。
- 设备上的其他操作(点击、输入、元素树、截图、视频、通过 adb 的 logcat)使用 limrun-android-emulator。
- 默认签名路径不需要用户凭据:`lim gradle build . --sign --upload myapp.aab`。
- 首次使用 `--sign` 时,Limrun 生成上传 keystore,将其作为组织为该应用托管的签名密钥,并用它签名;之后同一应用的每次 `--sign` 构建从任何机器或 CI 都使用同一密钥,保持 Play Store 上传匹配。
- 签名密钥按 Android application ID 命名,从 `app.json`(Expo)或 `app/build.gradle(.kts)` 检测;检测失败或选错 flavor 时传 `--application-id <id>`。
- `--sign` 使 `bundleRelease` 成为默认任务;如果显式 `--task` 列表中没有 bundle 任务,构建会在开始前失败。
- SUCCEEDED 构建意味着 AAB 带有签名(服务器在上传前验证),除非用户要求,否则不要重新验证工件。
- 构建开始前留意并转述以下行:`Signing with the organization's upload key for <app> (newly generated).` 表示此应用首次构建,密钥现在存在于整个组织;`Signing with the organization's upload key for <app> (existing).` 表示按预期复用托管的密钥。
- 当应用已有注册的上传密钥(现有 Play 列表)时,改用用户 keystore 签名:`lim gradle build . --keystore upload.jks --keystore-password "$KS_PASS" --key-alias upload --key-password "$KEY_PASS" --upload myapp.aab`。
- 四个 BYO 标志必须一起传;密码可来自 `LIM_KEYSTORE_PASSWORD` 和 `LIM_KEY_PASSWORD`,而不是 argv。
- 添加 `--save-key` 托管提供的密钥,以便后续构建去掉标志并使用普通 `--sign`。
- `--save-key` 拒绝覆盖:如果该应用已托管不同密钥,它会在创建任何实例前失败。
- 从用户收集:keystore 文件路径(`.jks` 或 `.p12`);绝不提交它或将字节粘贴到文件;keystore 密码和 key 密码(通常相同);key alias(未知时用 `keytool -list -keystore <file>` 查看)。
- 识别 BYO 路径失败字符串 `The organization already has a different upload key escrowed for <app>`:这是 `--save-key` 冲突。带 `--sign` 的构建使用托管密钥;去掉 `--save-key` 以仅本次构建用提供的 keystore 签名,或询问用户哪个是真实上传密钥。
- 识别 BYO 路径失败字符串 `Signing with your own key requires ... as well`:BYO 标志组不完整;消息列出确切缺失的标志。
- 识别 BYO 路径失败字符串 `signing <field> contains an unsupported character`:密码或 alias 含有 ISO-8859-1 之外的字符。用 keytool(`-storepasswd`、`-keypasswd` 或 `-changealias`)就地改为 Latin-1 值;绝不要重新生成密钥本身,因为那会改变上传密钥。
- 有 Play 凭据时(通过 `--playstore-service-account` 的服务账号 JSON,或通过 `--playstore-access-token` 的访问令牌),构建直接发布已签名 release AAB,无需浏览器:`lim gradle build . --sign --upload-to-playstore --playstore-service-account sa.json --auto-version-code`。
- `--auto-version-code` 使服务器在构建前从 Google Play 解析下一个空闲 versionCode,并写入工作区副本(Expo 项目为 `app.json` 中 `expo.android.versionCode`,原生 Gradle 项目为常规 `app/` 模块构建脚本中的单个字面量 `versionCode`),因此重复发布不会冲突。
- 不用 `--auto-version-code`,或项目使用计算或 flavor 拆分的 versionCode(它在请求时拒绝)时,自行管理 versionCode。
- 没有 Play 凭据时不能运行发布本身:这是带 Google 登录的浏览器流程。准备工件,上传为资产并移交:`lim gradle build . --sign --upload <app>-v<versionCode>.aab`。
- 告诉用户打开 https://console.limrun.com,在 **Secrets** 页面点击 **Connect Play Console**,用有应用发布权限的 Google 账号登录(会话仅在浏览器中,不存储任何内容)。
- 然后在 **Registry** 页面点击已上传 AAB 的 **Publish to Play Store**,输入 package name(application ID)。
- 应用列表必须已存在于 Play Console。
- Google Play 要求 versionCode 从未出现过:`--auto-version-code` 在发布构建中处理;否则在构建前提升 `app/build.gradle(.kts)` 中的 `versionCode`(Expo:`app.json` 中的 `expo.android.versionCode`)。
- 识别 `--sign` 路径失败字符串 `Cannot determine the Android application ID for signing`:检测未找到 `app.json` android.package,也未在 `app/build.gradle(.kts)` 中找到 `applicationId`;传 `--application-id <id>`。
- 识别 `--sign` 路径失败字符串 `--sign produces a Play-ready signed AAB; include a bundle task`:显式 `--task` 列表没有 bundle 任务;添加 `bundleRelease` 或去掉 `--task`。
- 识别 `--sign` 路径失败字符串 `the built AAB carries no signature`:服务器构建后检查发现未签名 bundle;签名配置未应用。不是用户代码问题;重试,若持续则报告。
- 构建错误由你修复:如果构建失败,读取错误输出,修复代码,重新构建;不要请用户修复构建错误。
- 实例复用按 git worktree:命令从 cwd 的 worktree 解析记住的实例;传 `--id <gradle-instance-id>`(来自 `lim gradle list`)以指定特定实例。
- versionCode 必须为每次 Play 上传递增;发布构建优先用 `--auto-version-code`。发布被拒说 version code 已存在意味着提升、重建、重新发布;如果发布 RETRY 报告它,之前尝试已成功,不要再次发布。
- Application ID 检测读取第一个未注释的 `applicationId`;Flavor 特定 ID 和动态 Gradle 逻辑超出范围,那里用 `--application-id`。
- Keystore 密码必须非空且为 ISO-8859-1;空密码和 Latin-1 之外字符在请求时被拒绝,而不是构建几分钟后失败。
- 保持同步文件小且不在 build 目录:根级 `build/`、`.gradle`、`.kotlin` 和任何 `local.properties` 从不同步,`.gitignore` 文件(包括嵌套)会被遵守;用 `--ignore <regex>` 忽略其他大本地工件,用 `--include <regex>` 强制同步构建需要的被 gitignore 的输入。
适用边界 · 注意事项
- iOS 构建应使用 limrun-xcode,而不是本技能。
- Expo dev-client 循环(Metro、热重载)应使用 limrun-expo-development;本技能仅用于其 Android Debug 构建。
- 没有 Limrun CLI/账号或远程 Gradle 沙箱不可用时无法使用。