我想在手机上修一个bug。不是"在手机上审个PR"那种,是真的打开一个项目,让AI代理写代码、跑起来、看结果、发布出去。
我找到的每一个工具都是聊天应用,背后连着别人的服务器。所以我做了自己想要的东西:AndroPI,一个跑在手机本地的AI编程代理。开源,MIT协议,没有后端。
![]()
现在它能用了。但走到这一步,全程都在跟Android打架。
计划本来很简单
拿pi——一个用TypeScript写的开源编程代理,前面套个Flutter界面,完事。
问题是:pi需要Node.js,还需要git、shell、ripgrep、ssh、curl。全都要跑在手机上。
Android不会运行你的二进制文件
第一堵墙。我把一个Node二进制丢进应用的数据目录,试着执行它。
权限拒绝。
从Android 10开始,你不能从应用的可写存储里执行文件。应用唯一能运行原生代码的地方是它的原生库目录。而打包器只把命名为lib*.so的文件放进去。
于是我就这么干了。Node.js以libnode.so的身份进APK,git是libgit.so。它们不是库。Android也不检查。
二进制来自Termux软件源。一个脚本下载.deb包、把二进制抽出来、用lief重写它们的库名——因为像libicuuc.so.78这种真实依赖也得改成libicuuc_78.so,否则打包器会把它丢掉。
我最喜欢的一处:容器启动器是个shell脚本,它以libbox.so的身份发布。Flutter构建每次都抱怨它"failed to strip debug symbols"。对,它就是个shell脚本。
没有root的真Linux
一个不能apt install的代理只能算半个代理。它迟早会要Python,或者更新的Node,或者某个我没打包的构建工具。
所以AndroPI用proot跑一个Debian(或Alpine)用户空间。不需要root。应用直接从Docker Hub的registry API拉官方镜像、自己解包分层。代理的shell就跑在里面。
在手机上,从聊天窗口里apt install python3。那一下感觉不错。
没人提醒你的事
我的ISP劫持DNS。代理的网页搜索一直失败。原来是运营商在重定向它不喜欢的站点查询。我在Node宿主里加了DNS over HTTPS。现在不管网络怎么想,代理都能搜。
模型会发垃圾参数。有个模型一直用offset: "None"调用读取工具——一个Python风格的字符串,塞进数字字段。校验失败,整个运行挂掉。我加了一层小逻辑,在校验前清洗工具参数。
前台服务吃掉了我的通知。应用运行时显示"Agent is working",结束时显示"pi is done"。完成通知从没出现过。两个通知用了同一个ID 1。服务停止时,Android把ID 1移除了。我花了相当尴尬的一段时间才发现,而且只是因为当时在录演示视频才抓到。
73 MB。心疼。
第一个release版APK是73 MB。我以为Flutter是胖的那个。并不是。
大约80%的体积是运行时。Node单独压缩后15 MB。Node做Intl需要的ICU数据,又是15 MB。
我最初的想法是把代理打包成一个压缩文件。结果登录坏了。pi通过import()加载它的OAuth流程,路径是运行时拼出来的,打包器跟不了。
于是我保留包结构,做了件无聊的事:删掉pi预构建的CLI包(8 MB,SDK入口从不加载)、从node_modules里剔除文档、TypeScript源码和README图片、就地压缩每个JS文件。代理包从16.6 MB降到8 MB,APK从73降到63。之后又加了armv7和x86_64构建,因为Termux两个架构都有包。
然后Play Store说了两次不
第一次:"所有文件访问权限"。我申请了MANAGE_EXTERNAL_STORAGE,好让你打开手机上任何文件夹里的项目。谷歌只允许文件管理器和少数几个类别用这个权限。编程代理不在名单上。
合理。工作区本来就住在应用存储里,只有一个功能需要它。我把构建拆成两个flavor:Play版去掉这个权限,文件通过系统选择器进来、通过MediaStore或分享面板出去。GitHub版保留完整版本。
第二次:前台服务。Android 14要求每个前台服务都有一个类型,而"运行一个AI代理"不在其中。所以它是specialUse,这意味着要写一份书面说明,还要录一段视频展示应用在后台时的通知。就是在那段视频里,我发现了那个通知bug。
它今天能做什么
- 跟代理聊天,看着代码流式输出
- 实时HTML预览,页面边写边更新
- 带apt、pip、npm的Debian容器,外加多标签终端
- GitHub设备码登录,clone、commit、push、PR
- 部署到GitHub Pages、Vercel或你自己的服务器(走SSH)
- 审批模式、计划模式、可撤销一次运行的检查点
- MCP服务器、技能、后台任务
模型你自己带:Claude、GPT、Gemini、OpenRouter。你的密钥留在你手机上。中间没有我的服务器,因为根本没有我的服务器。
试试看
- 网站和下载:https://andropi.imtaqin.id
- 源码:https://github.com/imtaqin/andropi
如果你在APK里塞过什么奇怪的东西,我想听听你是怎么让它过审的。如果你发现bug,开个issue。多半是我造成的。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.