乐于分享
好东西不私藏

谷歌一周搓了25万个App,我在手机终端里48秒搓了一个

谷歌一周搓了25万个App,我在手机终端里48秒搓了一个

上篇文章介绍了在手机termux下安装codex cli,在这个基础上我干了一件更狠的事,在手机上开发编译apk。

前两天谷歌AI Studio上线,一周就搓出25万个Android App,99%的用户之前从没写过代码。随便打几行提示词,一个番茄钟、一个拍照翻译器、一个木鱼功德App就出来了。

看起来,Android开发的门槛已经被踩到了地板上。

但有个问题没人提:这些App是怎么装到手机上的?

答案是——你得有一台电脑,装上Android Studio,下载几个GB的SDK,然后点Run。

那如果我告诉你,我连电脑都没用,直接在手机终端里,把一个Android APK从零编译出来了呢?


我干了什么

一部手机,装个Termux,敲几行命令,48秒,一个54KB的APK就出来了。

能装,能跑,能用。

不是什么Hello World,是一个正经的AI语音助手——能录音、能语音识别、能调大模型聊天、能用TTS把回答念出来,还有悬浮球拖来拖去。

而且,我用了两种方式:
  1. Gradle构建——和电脑上Android Studio一模一样的流程,./gradlew assembleDebug,一行命令出包
  2. 纯命令行手工编译——aapt2、javac、d8、zip、apksigner,七步流水线,不依赖任何构建工具

两种都跑通了。


核心突破:一行配置救活Gradle

先说为什么这事儿之前没人干成。

Gradle构建Android项目时,AGP会从Maven下载aapt2——一个资源编译工具。但下载下来的是x86-64版本

Termux跑在ARM64上。

x86-64的二进制在ARM64上直接跑,结果就是:

Exec format error

就这么致命。

以前的解决办法是绕过Gradle,用手工编译。但现在有了更优雅的方案——在gradle.properties里加一行:

android.aapt2FromMavenOverride=/data/data/com.termux/files/usr/bin/aapt2

告诉Gradle:别下载Maven上的aapt2了,直接用Termux系统里已经装好的ARM64版本。

一行配置,Gradle瞬间复活。


实测:48秒,32个任务,一个APK

我拿一个AI语音助手项目做了测试。

项目信息:

  • 包名:com.ai.voiceassistant
  • 7个Java文件,1206行代码
  • 目标SDK:Android 34
  • 最低支持:Android 8.0

构建过程:

./gradlew assembleDebug
> Task :app:compileDebugJavaWithJavac
> Task :app:dexBuilderDebug
> Task :app:packageDebug
> Task :app:assembleDebug

BUILD SUCCESSFUL in 48s
32 actionable tasks: 32 executed

48秒,32个任务,全部通过。

产出的APK:54KB。adb install直接装。

和电脑上的体验几乎没有区别。唯一的区别是——你是在手机终端里敲的命令。


手工编译:七步流水线,每一步都看得见

如果你想搞清楚一个APK到底是怎么从源码变成可安装文件的,手工编译是最好的学习方式。

七步:

aapt2 compile  → 编译资源文件(XML/PNG → .flat)
aapt2 link → 生成APK骨架 + R.java
javac → 编译Java源码
d8 → .class → .dex(Android字节码)
zip → 把dex塞进APK
zipalign → 4字节对齐
apksigner → 签名(v1+v2+v3)

核心代码:

# 逐文件编译资源(aapt2的--dir在Termux下有bug)
find "$SRC/res" -type f | while read f; do
aapt2 compile "$f" -o "$BUILD/compiled_res/"
done

# 链接生成APK
aapt2 link --manifest AndroidManifest.xml -I android.jar \
-o app-unsigned.apk --java gen --auto-add-overlay

# 编译Java
javac -source 17 -target 17 -classpath android.jar -d classes ...

# DEX转换
d8 --min-api 26 --output dex/ classes/*.class

# 打包、对齐、签名
cp app-unsigned.apk app-merged.apk
zip -j app-merged.apk dex/classes.dex
zipalign -f 4 app-merged.apk app-aligned.apk
apksigner sign --ks debug.keystore --out final.apk app-aligned.apk

每一步干什么,清清楚楚。

以前在Android Studio里点一下Run就完事的事,现在你亲手走了一遍。这种理解,在调试构建问题时特别有用。


两种方案怎么选?

Gradle构建手工编译
适合标准项目、有第三方库简单项目、学习原理
依赖Gradle + AGP只需SDK命令行工具
速度48秒更快(跳过Gradle开销)
依赖管理自动下载全部手动
上手难度

我的建议:先用Gradle日常开发,有空时用手工编译走一遍流程


我踩过的四个坑

坑1:aapt2 --dir会崩

Termux的aapt2(2.19版)用--dir编译整个资源目录会段错误。解决:逐文件编译。虽然看着原始,但稳。

坑2:uses-sdk导致签名失败

AndroidManifest.xml里写了<uses-sdk>,apksigner报v1签名错误。解决:不让aapt2 link自动生成<uses-sdk>

坑3:TTS念Emoji

大模型回复带Emoji,TTS引擎念出来声音很诡异。解决:正则过滤掉Emoji再送给TTS。

坑4:ASR和TTS互相打架

TTS说话时麦克风会把声音也录进去,形成回声。解决:加1.5秒冷却时间。


实际项目长什么样

这个"AI语音助手",核心链路就一条:

说话 → 语音识别 → 大模型回复 → TTS念出来

7个Java文件的分工:

文件干什么行数
VoicePipeline.java语音管线状态机(IDLE→LISTENING→THINKING→SPEAKING)293
FloatWindowService.java悬浮窗服务+脉冲动画284
MainActivity.java配置界面240
LlmClient.java大模型HTTP客户端,对接OpenAI兼容API172
TtsManager.java语音合成+Emoji过滤120
ConversationManager.java对话历史管理64
DebugLog.java调试日志33

全部Java,没有Kotlin,没有第三方库。54KB。


环境搭建速查

# 基础工具
pkg update && pkg install -y openjdk-17 gradle aapt2

# Android SDK(手动下载)
mkdir -p ~/android-sdk/{platforms,build-tools}
# 放入 android-34 platforms 和 build-tools 34.0.0

# 环境变量
export ANDROID_HOME=$HOME/android-sdk
export JAVA_HOME=$PREFIX/lib/jvm/java-17-openjdk

总占用:SDK约200MB,JDK约150MB。


Vibe Coding和手动编译,到底什么关系?

说实话,不矛盾。

谷歌AI Studio的Vibe Coding降低了门槛——不会写代码的人也能做出App。这是好事。

但如果你想理解App是怎么构建的,想掌控每一个字节是怎么变成APK的,想在没有电脑的时候也能独立开发——Termux给了你这个能力。

Vibe Coding是"让AI帮你搓"。

Termux手工编译是"你自己搓,每一步都知道发生了什么"。

两种方式,看你需要哪种。


试试看

如果你有一部Android手机,装个Termux,花10分钟搭好环境,然后:

# 验证环境
java -version
aapt2 version
gradle --version

# 创建一个最简单的项目,跑一遍构建

体验一下在手机终端里编译出APK的感觉。

那种"我亲手把源码变成了可安装文件"的掌控感,是点一下Run给不了的。


以上内容全部在Termux里完成