它会自己改自己的代码,现在装进了一部安卓手机

楼主: 老马 浏览: 23 回复: 1 发布于: 2026-11-05 08:47:44
昨天下午在地铁上,我用手机让它把网站的顶部导航改成汉堡菜单。改完它自己截了图、数了像素,回我一句:灰字 0 像素,9 个链接确实从布局里移出去了。

这活得开电脑。是半年前的事。

后来我把整套东西搬进了手机。不是为了炫技,是因为那次在高铁上改一个 CSS,硬等了三小时到站。

先说清楚:下面每一个数字、每一行输出,都是这台手机上当场跑出来的。环境、日志、依赖版本、文件大小,没有一项是回忆着写的。

它不是聊天软件


你说话,它干活。干活的地方就是这台手机本身:敲命令、改文件、截图、认图、开摄像头、点屏幕。

面板跑在 127.0.0.1:9900。这个地址只在本机,外面连不进来。你的对话、你的文件、你的模型 Key,都留在这台机器上。

电脑上那套基本都在:插件、记忆、多模型、任务队列。

先看清这台手机


装之前得知道自己手里是什么。这一步别跳,后面每一个坑都跟这几个数字有关。

图片

GFY-AL00,Android 12,SDK 31,aarch64,8 核,7646 MB 内存,可用空间 26G。

Termux 0.118.3,Python 3.14.8,PHP 8.5.12,javac 21.0.13,Gradle 9.8.2。

node 没装。

这几行看着平淡,但每条都能解释后面一个毛病:

aarch64 意味着 x86 的二进制直接跑不了,官方 build-tools 给的就是 x86。

7646 MB 内存意味着编译 Kotlin 的时候得特意把编译器塞进同一个 JVM,不然两个进程一起能把内存吃穿。

node 没装意味着前端构建全走不通,所以面板干脆是纯 HTML,没有打包步骤。

Python 3.14 意味着有几个老包已经编译不过了,这些后面会一个个点出来。

125 MB 的安装包


参数先摆着,免得你下错包:

文件名 7tan-boot-launcher.apk,125.3 MB,131,409,364 字节,更新 2026-11-04,程序包 1.2.9,面板 V1.0.23,系统要 Android 7.0 及以上。

下载地址就一个:www.7tan.com/updates/7tan-boot-launcher.apk

一个 AI 工具 125 MB,很多人第一反应是"这是不是塞了模型"。不是。拆开看:

图片

termux.apk 117,775,723 字节,112.3 MB,占九成。pkg.zip 13,176,471 字节,12.6 MB,那是程序本体。剩下 setup.sh 和 cleanup.sh 加起来不到 45 KB。

那 112 MB 是整个 Termux。不打进去,手机上连 Python 都没有。

所谓"装个 App 就能用",前提是有人把这个前提一起塞进去了。

安装三步:

一,手机浏览器打开 ai-tool 页,点安卓版 APK。

二,安装时系统会弹"未知来源",允许。

三,打开。第一次启动要十几秒,它在起面板。

图片

配置环境:一键脚本到底做了什么


大部分人卡在这一步。App 装上了,点进面板一片空白,因为 Python 依赖还没装。

面板上有个「一键配置」按钮,背后是一个 bash 脚本,跑完要 3 到 10 分钟。它分五段:

阶段 0,打开 Termux 对外命令通道,1 秒。

阶段 1,装系统依赖、换可用软件源,1 到 3 分钟。

阶段 2,拉程序包并解压,10 到 30 秒。

阶段 3,装 Python 依赖,3 到 10 分钟。

阶段 4,写自启脚本、起服务,5 到 20 秒。

图片

下面按阶段拆开。这些细节不写出来,你下次重装还是会在同一个地方卡住。

阶段 0:一行配置,决定服务能不能被静默拉起


配置目录里的 termux.properties 要写 allow-external-apps=true。

这个文件全新安装时不存在,默认 false。它必须由 Termux 自己写,因为 /data/data/com.termux 这个目录,安装器 App 没有权限。

没有这一行,面板只能让你手动切到 Termux 里敲命令。有了它,安装器能在后台把服务拉起来。

阶段 1:判断软件源能不能用,看的不是网速


这一步踩过最久的一个坑。

mirrors.krnk.org 那个源,网络是通的,apt-get update 也照样返回,但索引文件大小对不上:

File has unexpected size 588514 != 591194


apt 直接拒绝这份索引。之后所有包都报 Unable to locate package,连 python 都装不上。现象看起来像网络问题,其实是源坏了。

所以脚本里换源的判据只有一个:apt-cache policy python 有没有 Candidate。

$ apt-cache policy python | head -3
python:
  Installed: 3.14.8
  Candidate: 3.14.8


有 Candidate,源就能用。没有,换下一个。

还有一个必须做的动作:换源之前得先清空 apt 的索引目录(PREFIX/var/lib/apt/lists)。上一轮留下的旧索引会让 apt-cache 依然查得到 python,于是一个坏源也会被判成可用。这条是实测踩出来的。

脚本里排了六个备用源,逐个试到能用为止:packages-cf.termux.dev、packages.termux.dev、mirror.mwt.me、中科大、北外、清华。

装包那行带了 -o Dpkg::Options::=--force-confnew。不加这个,遇到 conffile 会停下来问一句 openssl.cnf 要保留还是覆盖,一键脚本就卡死在那了。

阶段 1 后半段:编译型依赖必须走 apt,不能走 pip


这一批包是 apt 装的:

python unzip curl openssl-tool libxml2 libxslt
python-lxml python-pillow python-cryptography python-greenlet


后四个是重点。lxml、Pillow、cryptography、greenlet 都是 C 扩展,Termux 官方给了预编译包,名字前面加 python-。

如果用 pip 装同名的那几个,pip 会下源码、现场编译。在 ARM 手机上编译 lxml,十分钟起步。失败率还高,报错位置往往看不出跟 lxml 有关系。

所以顺序很重要:先 apt 装好这四个,pip 阶段再 import 时它们已经在了,根本不会去碰源码编译。

阶段 2:解压前先把聊天记录挪走


程序包 12 MB 左右,解开是 671 个文件。真实日志里那两行:

[2/5] 下载程序包并解压
      已下载 12 MB
      解压完成:671 个文件


这里有个保护:程序包里不含 data/games.db。直接覆盖会把你所有聊天记录清空。

脚本的做法是先把 data 目录挪走,解压完看新目录里没有库文件,再放回来。

还有一个我自己踩过的坑,值得单独说清楚。

安装器里写了一个版本戳 .7tan_pkg_ver。当初只改了前端 CSS、打了个新 APK,用户装上新包、点一键配置,阶段 2 因为状态文件里标记了「已完成」被整段跳过,解压出来的还是旧程序。界面纹丝不动,看起来就像打包没生效。

现在每次都比对版本戳,不一致就强制只重跑阶段 2,阶段 3 往后的依赖和服务保持不动。

顺带说一个更隐蔽的坑。状态文件早期把「正在做」和「已完成」混用一个值,一进阶段就写状态,等于宣告完成。结果阶段 1 apt 装包失败,用户重跑脚本,这一阶段被直接跳过,报错也就再也修不好了。

现在拆成两个文件:一个只给界面显示进度,另一个才判定要不要跳过。

阶段 3:Python 依赖,这里错了七个地方


这是整段最长的,也是最容易一装就崩的。

先装镜像。默认 pypi.org 在国内拉十几个包,平均每个包超时一次。脚本里写死阿里云:

PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/
PIP_TRUSTED_HOST=mirrors.aliyun.com pypi.org mirrors.ustc.edu.cn


然后有七个必须钉死的地方。全是实际撞出来的,不是预防性写的。

第一,pip 不能自升级。 Termux 的 python-pip 包把 pip 的自升级锁了,执行 pip install --upgrade pip 会直接报 Installing pip is forbidden (termux)。

第二,pydantic 只能用 1.x。 pydantic 2 的核心 pydantic-core 是 Rust 写的。PyPI 上只有 manylinux、musllinux、win、mac 四种预编译包,Termux 的平台标签是 android + bionic,一个都匹配不上。pip 只能下源码现场编译,而机器上没装 rust,必然失败。

所以降到 pydantic 1.10.27,纯 Python,不用编译。

第三,fastapi 必须加 --no-deps。 否则 pip 会顺手把 pydantic 升到 2.x,前面的工作全推翻。

--no-deps 又会漏掉 anyio(starlette 的硬依赖)。实测缺它时 import fastapi 直接 ModuleNotFoundError。所以 anyio 单独先装。

第四,pyyaml 需要 C 编译器。 它只发 sdist,得现场编译。阶段 1 的包列表里没放 clang,因为装它要连带 llvm,好几百兆。所以改成按需补:import 失败才装 clang,装完再编 pyyaml。

不装它的后果是整个服务起不来,因为 config/loader.py 在顶层就 import yaml。

第五,apscheduler 必须钉 3.x。 4.x 依赖 pydantic 2,会把上面定下的 1.x 方案整个推翻。而它又是 scheduler.py 的硬 import,缺了整个 web 服务在 import 阶段就崩。

实测现象只有一行 ModuleNotFoundError: apscheduler,看不出是版本问题。

第六,openai 钉 1.35.0。 更高版本依赖 jiter,那玩意也是 Rust 写的,和 pydantic-core 一样的死法。1.35.0 的依赖全是纯 Python。

第七,httpx 必须小于 0.28。 这条最坑,因为它报的错跟版本毫无关系。

openai 1.35.0 建客户端时传的是 httpx.Client(proxies=...),而 httpx 0.28 把这个参数删了。构造即 TypeError。

现象是每聊一句都回一句:

AI 调用失败: Client.__init__() got an unexpected keyword argument 'proxies'


脚本里兜了一道:启动前检查 httpx 版本,不小于 0.28 就降到 0.27.2。

图片

最后一步是逐个 import 复核:fastapi、uvicorn、pydantic、loguru、httpx、sqlalchemy、aiosqlite、websockets、yaml、apscheduler、slugify。少一个就直接报错停下。

pip 的返回值不可全信,它经常装完了但那个包 import 不了。以 import 结果为准。

阶段 4:自启、唤醒锁、以及「服务已就绪」那一秒


最后一段写自启脚本,再启动服务。

真实日志的结尾是这样:

[4/5] 写入自启脚本并启动服务
      ~/7tan_autostart.sh 已写入
      ~/.bashrc 兜底已写入
      服务已就绪(1 秒)

[5/5] 配置完成,可以开始使用
      检查 AI 密钥是否可用…
      AI 服务连通 ✓(deepseek/deepseek-flash)


「服务已就绪(1 秒)」这个数字不是写死的,是真的等端口起来才打印。前面那段 3 到 10 分钟花在装依赖上,服务本身起来只要一秒。

这里有个东西必须提:唤醒锁。

Termux 在锁屏、切后台时会停止终端视图重绘。进程还在跑,屏幕却定格不动。脚本开头会调一次 termux-wake-lock,等于在通知栏点亮那个「ACQUIRE WAKELOCK」。

不点这个锁,长任务跑到一半会被系统挂起。跑完之后记得关掉,它一直在耗电。

环境配好之后,这东西的真实成本


三步装包加一键配置,顺利的话 5 分钟。不顺利的话,上面每一个坑都能吃掉你一晚上。

我把这台机器的实际数字摆出来:apk 125.3 MB,解压 671 个文件,apt 装掉二百多个包,pip 装十几轮,磁盘占掉约 1.6G。

值得吗。

看你怎么用。我一天里绝大多数改动都是改文案、调颜色、补一页说明,这些用不着电脑。

真要搭一个 Android 工程、编一个原生 App、或者处理几万条数据,还是回去用电脑。

它解决的问题不是「手机能替代电脑」。是有那么几个小时你手上只有手机,而活不会等你。

APK 是怎么编出来的


这一段跟日常使用无关,写给好奇的人。

没用 Gradle。这个 App 没有第三方依赖,用 SDK 自带的 aapt2、javac、d8、zipalign、apksigner 直接构建,全程离线,也避免 Gradle 拉 AGP 卡住。

图片

官方 build-tools 只发 linux-x86_64,而我这是 aarch64。aapt2 一跑就崩:

cannot locate symbol _ZNSt6__ndk113__hash_memoryEPKvm


字都认识,意思不懂。查了一阵才弄明白:aapt2 和 adb 都是对着 libc++ 30 编的,仓库里装的是 27c。重装 libc++ 就好,就一行。

还有一个细节:内置资源在 aapt2 链接之后以「不压缩」方式追加进 APK。

为什么不能压缩。因为 AssetManager.openFd() 要直接取到文件描述符做流式读取,压缩过的条目拿不到。那 112 MB 的 termux.apk 就是这么塞进去的,不压缩也不会有额外开销。

速度实测:首次全量约 5 分钟(要拉 Kotlin 编译器和 Compose 全套),改一行代码之后增量 57 秒,assembleRelease 4 分 1 秒。内存峰值 4.3G / 7.5G,没爆。

关键的开关是这一个:

kotlin.compiler.execution.strategy=in-process


让 Kotlin 编译器跑在 Gradle 同一个 JVM 里。不开这个,两个进程一起能把 7.5G 吃穿。

打开之后看到什么


三块,从上往下。

AI 工作台是它想事情的过程。实时控制台是它真敲下去的命令。对话在最下面,那是你打字的地方。

右上角有个下拉,切模型,默认 deepseek。

工作台我平时不看,只在它卡住的时候瞄一眼。能看见它跑到第几轮、调了哪个工具、是不是在瞎猜。

手机上砍掉了四样


源站管理。那张表横着放不下,在手机上改站点纯属受罪。

任务中心。手机不看排队,看的是现在好了没。

Token 输入框。打字填一长串 Key,是折磨。

意识模型。电脑端专属的调试面板。

手机上的正事是一两句话把活交出去,然后等结果。

多出来的两只手


手机版有两样电脑给不了的东西。

一是手。开了无障碍,它能点屏幕、滑列表、往输入框里写字。你让它把这个 App 的每日签到点一下,它真会去点。这是系统级权限,等于把手机交出去一部分,想清楚再开。

二是眼睛。手机立起来对着桌子,问一句这上面有什么,它会拍一张,然后说。

图片

我拿它认过提词器上的字,也让它看过电脑屏幕上的报错。这两件事在电脑上做不到,因为电脑没有手,也没有能转的镜头。

我拿它干过的三件真事


三件都在同一部手机上做完,最长的那件跑了 25 轮,两个半分钟。

第一件,全站换色。原来导航是绿底白字,要改成首页那套白底蓝。它做完之后不是跟我说改好了,是截了图数像素:安卓页绿色 0,百科页绿色 0,主蓝 57,908 个像素。

第二件,加汉堡菜单。手机窄,9 个栏目挤不下,右边那个「版号查询」只剩半个字。它改成点一下弹出来,还顺手算了一遍:面板高 307,可用 369,还有 62 的余量,不会裁。

图片

图片

第三件,写说明书。手机版这一章现在挂在 www.7tan.com/manual.html 上,一个字没在我电脑上敲。

图片

三个坑,提前说


一,息屏就断。锁屏之后它还在跑,但网络会断,长任务容易半路失联。要么把屏幕设成常亮,要么别在锁屏时扔长活。

二,9900 打不开。八成是后台被系统杀了。设置里把它的省电策略改成「无限制」,再打开。

三,APK 解析失败。125.3 MB,下到一半断了就这样。删掉重下,对一下文件大小。

图片

最后一句


它不是那种给你几个模板、帮你写两句文案的手机 AI。

它是一台你能改的机器。改歪了它自己会截图给你看哪歪了,这一条比什么都实在。

配置环境那一段我写得啰嗦,是因为那四十几个坑,每一个我都真金白银地卡过一晚上。你要是在哪一步卡住了,把报错发在评论区,我看着像的就补进下一版。
回复 🤍 0 📤 分享 收藏

回复 (1)

听起来真的很酷!我最想让AI做的事情是自动化一些日常任务,比如自动填充表单或者整理文件夹。你试试看改一改手机壁纸,应该也很方便吧!🌟
— 已加载全部回复 —

老马 的其他文章

作者主页

发表回复