我是怎么用 Typecho 插件体系和 Flutter 做出 Typecho 安卓 App 的
我一直想给自己的 Typecho 博客做一个真正能在手机上用的管理 App。
不是那种打开后只是套一层网页的 App,而是可以在手机上看后台概况、写文章、发时光机、传图片、审评论、清缓存的工具。博客本身还是 Typecho,内容也还是原来的内容,只是我希望它在手机上有一个更顺手的入口。
后来这个想法就变成了 XBlog:服务端用 Typecho 插件扩展,客户端用 Flutter 写安卓 App。
一开始我为什么没走 WebView
最开始当然也想过最省事的做法:直接用 WebView 打开后台页面。
但真要做的时候就会发现,这个方案很快会卡住。Typecho 后台是给桌面浏览器设计的,手机上写文章、传图片、切分类、审评论并不舒服。更麻烦的是,如果 App 依赖后台 HTML 结构,后台主题、插件、页面细节一变,客户端也要跟着抖。
所以我最后决定把它拆开:
- Typecho 继续负责内容管理。
- 插件负责把后台能力封装成接口。
- Flutter 负责手机端页面和交互。
这样做会多写一些代码,但边界很清楚。Flutter 不需要猜后台页面长什么样,Typecho 也不需要被改成另一个系统。
服务端:先做一个 XBlogBridge 插件
我在 Typecho 里写了一个插件,叫 XBlogBridge。
它做的事情很直接:注册一个统一入口:
/action/xblog然后通过 route 参数区分不同功能。比如健康检查、仪表盘、文章、评论、时光机、设置这些,都走这个入口。
我还专门做了一个 /health,因为联调时最怕 App 提示“接口不是 JSON”,结果查半天才发现是 PHP warning、插件目录放错、插件没启用,或者 action 没注册。先测 /health,能省很多时间。

图 2:我把 XBlogBridge 放在 Typecho 和 Flutter 中间,让客户端只面对稳定的 JSON 接口。
鉴权也没有复杂化。插件后台配置一个 App Token,Flutter 请求时带上:
X-XBlog-Token: ***真实 Token 我不会写进代码。这个东西放在插件配置里,必要时可以随时换掉。
我给插件补了哪些接口
做 XBlogBridge 的时候,我不是只做文章列表,而是按“手机上真的要管理博客”来补能力。
首先是仪表盘。App 打开后要能看到站点概况,比如文章数、页面数、草稿数、待审核评论数、时光机数量、最近文章和最新评论。这样手机上扫一眼,就知道博客有没有新评论、最近内容状态怎么样。
然后是文章管理。这个部分最复杂,因为不只是标题和正文。真正编辑一篇 Typecho 文章,还要处理分类、标签、slug、摘要、封面图、附件、评论开关、发布状态。后来我把这些都接上了,编辑旧文章时也能回填这些字段。
评论管理也做了。手机上最常见的场景其实是快速处理评论:待审核的点通过,垃圾评论点垃圾,必要时回复或删除。所以 App 里做了全部、待审核、已通过、垃圾几个筛选,已经通过的评论就不再显示“通过”按钮,少一个没必要的操作。
时光机是我现在的BLOG用的HandSome主题带的一个功能,是我很想保留的功能。XBlogBridge 里既支持自己建的 xblog_moments 表,也兼容 Handsome 的时光机/说说模式。这样不用放弃原来博客主题里的习惯。手机端可以发文字、图片、链接,也可以发私密动态。
最后还有一些维护类接口,比如读取设置、分类标签、上传图片、清缓存。它们看起来不起眼,但 App 想真正可用,这些能力都得有。
Flutter 端:把后台能力做成 App
Flutter 这边我写得比较克制。
网络请求没有上很重的封装,主要就是用 http 包,把站点地址和 /action/xblog?route=... 拼起来,再统一带上 Token。接口返回后转成 App 里的模型,页面只关心数据,不关心 Typecho 数据库怎么查。
登录页也很简单:填站点地址,填 App Token,然后连接真实后台。Token 输入框支持显示和隐藏,这个小细节挺重要,因为手机上复制粘贴 Token 时很容易输错,但明文显示又有旁边人看到的风险。
App 里主要做了几个页面:
- 仪表盘:看站点概况、最近文章、最新评论和待审核提醒。
- 文章编辑器:写文章、保存草稿、发布、编辑旧文章、删除文章。
- 时光机:发文字、本地图片、链接和私密动态。
- 评论:筛选、通过、回复、标记垃圾、删除。
- 设置:站点信息、主题切换、缓存清理等。

图 3:Flutter 负责把插件接口变成手机上的真实操作界面。
图片上传这个坑,我没有用现成 picker
图片上传是这次比较折腾的地方。
一开始很容易想到用 image_picker 或 file_picker,但我最后没有引入它们,而是自己在 Android 原生层做了一个选择图片的通道。
Flutter 侧调用一个 MethodChannel:
xblog/native_pickerAndroid 侧用系统的 ACTION_OPEN_DOCUMENT 打开图片选择器。用户选中图片后,我把图片复制到 App 缓存目录,再把本地路径返回给 Flutter。Flutter 拿到路径后,再用上传接口传给 Typecho 插件,插件返回图片 URL。
这样做的好处是链路完全可控。选图、读文件、上传、返回 URL,每一步出问题都比较好查。而且项目也少了几个第三方依赖。
后面时光机图片也顺手支持了三种解析:img、Markdown 图片和普通 URL 图片。这样不管内容来自哪里,App 里都尽量能显示出来。
文章编辑器比我想象中麻烦
写文章这个功能,看起来只是一个标题框和正文框,但真做起来细节很多。
新建文章要能发布,也要能保存草稿。编辑文章时,不仅要拉正文,还要把分类、标签、封面、摘要、slug、附件、评论开关都回填回来。否则手机端改一次文章,原来后台里设置好的东西就可能丢。
所以我后面专门补了这些字段的读取和保存。这样手机上改文章时,不会只是“改正文”,而是真的像一个简化版后台。
我还加了正文预览和插入图片。图片上传后可以插入到正文里,也可以作为封面或附件。这个体验比在手机浏览器里操作后台舒服很多。
评论和时光机,是我觉得最适合手机处理的部分
文章长编辑可能还是电脑舒服,但评论和时光机非常适合手机。
评论通常是碎片时间处理的:看到新评论,点进去,通过、回复、删除,几秒钟就能完成。App 首页的待审核红点也是为这个准备的,看到了就处理,不用特意打开后台。
时光机就更像手机场景了。拍了图,写一句话,加一个链接,直接发布。这个功能如果只能在桌面后台用,其实就少了很多“随手记录”的味道。
所以我在时光机里支持了本地图片上传、手动图片 URL、链接 URL 和私密开关。它不复杂,但很贴日常使用。
打包和交付
最后我把 Flutter 部分整理成可以覆盖到工程根目录的文件包。
新建工程大概是这样:
flutter create xblog_final然后把 XBlog 的 Flutter 文件覆盖进去,执行:
flutter clean
flutter pub get
flutter run安卓 release 包则用:
flutter build apk --release我也把图标、启动页、网络配置、Android 原生入口这些一起整理进去了。后面真要正式发布,再把包名、签名、图标细节继续收拾一下就行。
安全上我比较在意的点
这类 App 最容易犯的错,是把后台账号、密码、Cookie 或 Token 直接写死。
我没有这样做。App 只需要站点地址和 App Token,Token 来自 Typecho 插件配置。
另外,插件里也做了一些兼容处理,比如老 PHP 环境里函数不存在时 fallback,返回 JSON 前清掉 PHP warning 产生的 HTML 输出。这个细节很现实,因为 Typecho 站点经常跑在各种不同 PHP 环境里,不能假设每台服务器都完美。
小结
这次做 XBlog 安卓 App,我最满意的不是某个页面,而是这个结构本身。
Typecho 还是原来的 Typecho,插件把文章、评论、时光机、上传、设置这些能力整理成接口;Flutter 则把这些接口做成手机上能顺手操作的 App。
它不是一个“大而全”的博客客户端,但已经覆盖了我最常用的移动端维护场景:看状态、写文章、传图片、发时光机、审评论、清缓存。
对个人博客来说,这就够有意义了。电脑前适合认真写长文,手机上适合处理那些随时发生的小动作。XBlog 做的,就是把这两种使用方式接起来。