前言

Android 项目很适合交给 Codex 做一部分活,也很容易被 Codex 搞乱。

原因不复杂。Android/Kotlin 项目不只是几段 Kotlin 代码。它还有 JDK、Gradle、Android Gradle Plugin、Kotlin 插件、SDK、Manifest、资源文件、签名配置、模拟器和真机环境。任何一环对不上,./gradlew assembleDebug 就会停下来。

所以我不太建议让 Codex 直接「生成一个 APK」。这个说法太宽。

更稳的方式是把 Codex 放进一个短闭环里:读项目、做小改动、跑 Gradle、看错误、修补、留下 diff。

这篇记录的是我会怎么在 macOS 上组织这套流程。


1. 环境比提示词更要紧

Codex 写 Android 代码之前,本机环境要能独立构建项目。

我会把这几件事查清楚:

  • macOS 版本和芯片架构。
  • Android Studio 能不能正常打开项目。
  • JDK 是不是项目需要的版本。
  • ANDROID_SDK_ROOT 是否正确。
  • sdkmanageradbemulator 是否在 PATH 里。
  • ./gradlew assembleDebug 是否能跑。

基本检查命令:

sw_vers
uname -m
java -version
./gradlew --version

Android SDK 常见路径是:

$HOME/Library/Android/sdk

可以把 SDK 工具加入 ~/.zshrc

export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
export PATH="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$PATH"

生效后检查:

source ~/.zshrc
sdkmanager --version
adb version
emulator -version

这些命令不通,Codex 后面给什么补丁都很难验证。


2. JDK、Gradle、AGP 不要靠猜

Android 项目里最常见的坑,不是 Kotlin 语法,而是版本组合。

JDK、Gradle、Android Gradle Plugin、Kotlin 插件、Compose Compiler 这些东西互相有要求。Codex 如果没有读到当前项目文件,很容易套一个旧模板。

让它改 Gradle 之前,我会让它看这些文件:

settings.gradle 或 settings.gradle.kts
build.gradle 或 build.gradle.kts
gradle/libs.versions.toml
app/build.gradle 或 app/build.gradle.kts

给 Codex 的要求可以写成这样:

阅读当前 Gradle 配置,保留项目现有版本体系。不要凭空升级 AGP、Gradle、Kotlin 或 Compose。需要新增依赖时,写清原因,并放到版本目录里。

这句话能挡住很多奇怪补丁。

如果项目已经有 Gradle Wrapper,命令行构建统一用它:

./gradlew assembleDebug
./gradlew testDebugUnitTest

不要让 Codex 混用本机全局 Gradle。Android 项目里,Wrapper 就是边界。


3. 模拟器和真机至少保留一个可用

Android 改动不能只看编译。

本地至少要有一种运行方式:模拟器或者真机。

模拟器相关命令:

sdkmanager --list
avdmanager list device
emulator -list-avds

Apple Silicon 机器上,系统镜像要匹配架构。一般会选择 arm64-v8a 镜像。具体能装哪些包,以 sdkmanager --list 输出为准。

真机调试检查:

adb devices

设备没有授权时,手机上会弹 RSA 授权窗口。这里不用让 Codex 猜,直接看 adb devices 输出就行。

我通常会把这个规则写给 Codex:

涉及 UI 或设备能力的改动,编译通过不算结束。能跑模拟器或真机时,需要说明使用哪个命令验证。

4. Codex 更适合做小块工程活

Android 项目里,我不太会让 Codex 接一整个 App。

比较适合它的任务是这种:

  • 给现有页面补一个状态。
  • 把网络请求接进 ViewModel。
  • 修一个崩溃日志。
  • 给一段业务逻辑补本地单测。
  • 整理 Gradle 依赖。
  • 给 release 构建补签名配置。
  • 让 CI 跑 assembleDebug 和单测。

这些任务都有一个共同点:改动可以被 Gradle 验证。

任务太大时,我会让它产出计划,但计划里不能只写漂亮话。要写文件、命令和风险。

示例:

检查当前 Android 项目,说明实现这个功能会涉及哪些文件、需要新增哪些依赖、构建命令是什么。暂时不要修改文件。

拿到计划后,挑一个最小切口开工。


5. 提示词要绑定构建命令

Android 任务的提示词,不需要写得很华丽。

我会固定写几个东西:目标、约束、输出格式、验证命令。

新增功能可以这样写:

目标:在现有 Android Kotlin 项目中实现一个简单的设置页,包含开关状态和保存逻辑。

约束:
- 保留当前 Gradle 和 Kotlin 版本,不做无关升级。
- 不引入新的三方库,除非项目里已经使用。
- 如果项目使用 Compose,就沿用 Compose;如果使用 XML,就沿用 XML。

输出:
- 直接修改项目文件。
- 说明修改了哪些文件。
- 运行 ./gradlew assembleDebug。
- 如果有业务逻辑,补一个本地单测并运行 ./gradlew testDebugUnitTest。

修 bug 可以这样写:

现象:{粘贴现象}
日志:{粘贴 logcat 或 stacktrace}
期望:{写清楚正确行为}

要求:
- 定位根因。
- 做最小修复。
- 不做无关重构。
- 修复后运行 ./gradlew assembleDebug。
- 能补测试时,补 src/test 下的本地单测。

这类 prompt 不漂亮,但 Codex 很容易执行。


6. 让 Codex 输出 diff,比输出解释更有用

Android 改动经常跨文件。

一个功能可能同时碰到:

  • app/build.gradle.kts
  • AndroidManifest.xml
  • MainActivity.kt
  • ViewModel.kt
  • res/values/strings.xml
  • src/test/...

这种时候,长篇解释没什么用。diff 更重要。

我会要求 Codex 在收尾时给这几样东西:

请给出:
- 修改文件列表
- 核心行为变化
- 已运行的命令和结果
- 没能验证的部分

如果它没有跑构建,就必须说清楚。不要把「看起来没问题」当成结果。


7. APK 构建和签名不要混在一起

Debug APK 和 Release APK 是两件事。

Debug 构建:

./gradlew assembleDebug

Release 构建:

./gradlew assembleRelease

Debug APK 通常由开发环境自动签名。Release APK 要用自己的 keystore。

签名信息不要写死在仓库里。常见做法是用 keystore.properties,并把它加入 .gitignore

示例:

storeFile=/absolute/path/release.jks
storePassword=change-me
keyAlias=release
keyPassword=change-me

Gradle 里读取这个文件,CI 里用环境变量或 Secret 注入。

我会给 Codex 明确写:

添加 Release 签名配置,但不要把 keystore、密码或真实路径提交到仓库。使用 keystore.properties 或环境变量,并更新 .gitignore。

这类要求不能省。


8. CI 里不要藏太多魔法

Android CI 最怕本地能跑,CI 不知道差在哪里。

GitHub Actions 里至少要固定:

  • JDK 版本。
  • Android SDK / Gradle 缓存策略。
  • 构建命令。
  • 测试命令。
  • 签名密钥注入方式。

一个简单 workflow 可以长这样:

name: Android CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '17'

      - uses: gradle/actions/setup-gradle@v4

      - name: Build debug APK
        run: ./gradlew assembleDebug

      - name: Run unit tests
        run: ./gradlew testDebugUnitTest

如果要做 release 签名,密钥走 GitHub Secrets。不要让 Codex 把 base64 后的 keystore 直接写进仓库。


9. Codex 常见翻车点

乱升版本

它可能会为了接入一个库,把 Kotlin、AGP、Gradle 都动了。

提示里要写:保留现有版本体系。新增依赖要说明原因。

编译没跑

Android 代码看起来对,不代表能过 Gradle。

./gradlew assembleDebug 是最低门槛。

Manifest 漏权限

网络、相机、定位、文件访问,都会牵涉 Manifest 权限。涉及系统能力的改动,要让 Codex 检查 Manifest。

Compose 和 XML 混写

项目用 Compose,就沿用 Compose。项目用 XML,就沿用 XML。混着写不是不行,但要有明确理由。

测试写得太假

有些测试只是创建对象,不验证行为。

要求它覆盖具体 bug 或业务规则,不要只补测试文件数量。

签名信息进仓库

这个问题最麻烦。

任何 keystore、密码、token、API key,都不应该进 Git。


10. 我会反复使用的几段话

检查项目:

阅读当前 Android 项目结构,说明 Gradle 配置、JDK 要求、主要模块、构建命令和测试命令。不要修改文件。

小功能:

在现有 Android Kotlin 项目中实现 {功能}。保留当前技术栈和版本,不做无关升级。完成后运行 ./gradlew assembleDebug,并说明修改文件和验证结果。

修崩溃:

根据这段 logcat 定位崩溃根因,做最小修复。不要重构无关代码。修复后运行 ./gradlew assembleDebug;如果逻辑适合单测,补 src/test 测试并运行 ./gradlew testDebugUnitTest。

Release 签名:

为 Android 项目添加 Release 签名配置。不要提交 keystore 或密码。使用 keystore.properties 或环境变量,并更新 .gitignore。完成后运行 ./gradlew assembleRelease。

CI:

添加 GitHub Actions Android CI,固定 JDK 17,使用 Gradle 缓存,运行 assembleDebug 和 testDebugUnitTest。不要把任何签名密钥写进 workflow。

结语

Codex 做 Android,不适合拿来赌一次性生成完整 App。

它更适合接一段段小工程活:改 Gradle、补页面、修崩溃、写测试、处理签名、搭 CI。

每段任务都绑住一个命令。能编译,能测试,能看到 diff。

这样用起来没那么神奇,但靠谱很多。