我把一个Android应用转换成了网页

Lobsters Hottest 工具

摘要

作者反向工程了Travelbound Android应用,发现它只是一个带有追踪和广告的网页,并使用HTTP Toolkit和已root的安卓模拟器将其转换为一个合适的基于网页的行程表。

<p><a href="https://lobste.rs/s/vhbvwc/i_converted_android_app_webpage">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/11 07:22

# 你的“应用”本来可以是个网页(所以我来帮你改了……) 来源:https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/ ### 为什么这非得是个“应用”? 今年夏天,孩子们就读的表演艺术学校要去迪士尼乐园参加一场歌舞演出。大家都很兴奋,但*我*的兴奋劲儿——至少——在被告知需要安装“Travelbound”应用(https://play.google.com/store/apps/details?id=com.vamoos.apps.travelbound)才能查看行程、交通安排和住宿详情时,稍微打了点折扣。 去他的。这明明就该是个网页。为什么非要让我装一个(又一个)破应用,就为了告诉我一些完全可以放在一份(更小、更快、更通用的)文档里的东西? > Android 应用截图,显示摘要行程:列出了“渡轮过境”、“酒店入住”、“司机住宿”、“迪士尼夏延酒店”和“欢迎晚宴”的时间,每项都配了一张漂亮但千篇一律的照片。(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#lightbox-p-attachment_29642) 我一点也没夸张。这个应用本质上就是文字、图片和指向PDF文件的链接,全部通过网络传输。 这个“应用”似乎只有两件网页做不到的事,而且这两件都算得上是“负功能”: 1. 它会向开发者报告与你的 Google 账号关联的追踪数据。 2. 它会向你展示由同一机构组织的其他旅行的广告(他们管这叫“灵感”)。 去。他。的。全。都。去。他。的。做网页会比这个好多了。不像这个应用,网页可以: 1. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-1) - 复制粘贴 - 打印 - 保存 - 添加书签 - 搜索 - 在几乎任何设备上使用 - (可能)更好的无障碍支持 我烦得够呛……所以我打算“修正”这个应用。看我的。 ### 拦截应用流量 距离上次通过网络流量逆向分析安卓应用(https://danq.me/2018/07/05/comic-chameleon/)已经有一阵子了,所以我得重新熟悉一下最佳方法。最后我是这样做的: 1. 在 Android Studio 的虚拟设备管理器里创建了一个新的虚拟设备。 2. 测试了 `adb shell` 可以工作,然后用 rootAVD(https://gitlab.com/newbit/rootAVD)获取 root 权限:`./rootAVD.sh system-images/android-33/google_apis_playstore/x86_64/ramdisk.img`。 2. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-2) 3. 冷启动后,运行 Magisk(https://github.com/topjohnwu/Magisk),调整设置让它自动授予 `su` 权限给任何请求的应用。 3. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-3) > HTTP Toolkit 应用在 MacOS 和模拟的 Android 手机上运行截图,启用了用户信任和系统信任。(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#lightbox-p-attachment_29644) 你的流量都归我了。到了这一步,就跟跑 Wireshark 或 TCPdump 差不多。 1. 运行 HTTP Toolkit(https://httptoolkit.com/)并让它拦截 AVD 的流量。它会安装一个(伪造的)VPN 提供商,把手机的流量通过代理路由出去。 4. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-4) 2. 从 Play 商店安装 Travelbound 应用。 3. 配置 HTTP Toolkit,使其仅代理 Travelbound 应用(这样信号更多,噪音更少)。 只花了几分钟试验,我就发现这个应用的工作原理是把用户名和密码拼接起来 5. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-5),然后用以下格式的 URL: > `https://travelbound.api.vamoos.com/api/itineraries/{username}-{password}` 这会返回一大坨 JSON,稍加解释就能发现它代表了应用所“展示”的*所有内容*。例如,包含: - 一个数组,里面是行程的每一段; - 一个数组,里面是准备展示给你的所有“灵感”广告; - 一个交叉引用的数组,包含其他部分引用的所有文件(图片等)。 > Firefox 显示 JSON 文档,聚焦于“你的渡轮过境”部分,附带一些 HTML。(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#lightbox-p-attachment_29645) 他们显然*还是*生成了 HTML 代码……所以我要再问一遍:*为什么这不能是个网页?* 稍加试验发现,S3 图片 URL 的过期时间比较短,所以即使内容没变,也需要定期重新获取 JSON。 6. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-6) ### 把它变成更好的东西 现在我有了所有需要的东西,去做出一个……*更好的*东西。我写了一个 Ruby 脚本,通过 Cron 定时任务运行,拉取最新的 JSON 并用它生成一个 HTML 页面。我选择完全跳过“灵感”(数据模式中的“overlayRows”),只列出: 1. 行程中的项目; 2. 所有*未*被灵感或行程引用的文件(这是一种偷懒的方法来汇总 PDF 下载链接)。 然后我把这个页面托管起来,加上了密码保护:就是最初给旅行团的那个密码。我把使用的原始 JSON 放在 `<code>` 元素里,这样如果后来出现了模式中我没看到但可能出现的部分,也可以检查。 > 一个简单样式网页的截图,显示关于渡轮的相同信息,以及一张甲板照片。(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#lightbox-p-attachment_29647) 我的网页没有那个“借用”信息的应用那么“漂亮”。但它体积小得多,而且免费获得了 Web 的所有标准功能。 有些人喜欢“应用”,这……好吧,我猜也是。但有些应用*本来*可以是个网页。特别是像这个应用一样,交付的内容已经是 HTML 写成的,并且通过 HTTP 传输……那它们*本来就应该*是个网页,对吧?我不明白我们怎么会走到“应用文化”这个地步!软件公司明明可以*让工作更轻松*(*也更便宜*:部署到大型应用商店可不是免费的!),却非要为了*用更少的功能*把 HTML 内容*传送给更少的人* 7. (https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#footnote-29641-7),而不是直接发布到网络上。 有些任务用“应用”确实是正确选择。Travelbound 不在其列。但至少*我*(以及我们旅行团里我分享出去的其他人)现在*可以选择*如何访问这些内容了。要么是一个 43MB 的应用(下载完额外内容后会膨胀到 124MB),附带追踪和广告;要么是一个 0.05MB 的网页(可选额外 35MB 的图片),提供更多功能,在更多设备上可用。我知道我会用哪一个! > Android 应用截图,显示摘要行程:列出了“渡轮过境”、“酒店入住”、“司机住宿”、“迪士尼夏延酒店”和“欢迎晚宴”的时间,每项都配了一张漂亮但千篇一律的照片。(https://bcdn.danq.me/_q23u/2026/07/travelbound-app-summary.png)×(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#attachment_29642) > HTTP Toolkit 应用在 MacOS 和模拟的 Android 手机上运行截图,启用了用户信任和系统信任。(https://bcdn.danq.me/_q23u/2026/07/http-toolkit-intercepting.png)×(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#attachment_29644) > Firefox 显示 JSON 文档,聚焦于“你的渡轮过境”部分,附带一些 HTML。(https://bcdn.danq.me/_q23u/2026/07/travelbound-api-json.png)×(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#attachment_29645) > 一个简单样式网页的截图,显示关于渡轮的相同信息,以及一张甲板照片。(https://bcdn.danq.me/_q23u/2026/07/untravelbound-webpage.png)×(https://danq.me/2026/07/09/your-app-could-have-been-a-webpage/#attachment_29647)

相似文章