ice 应用商店
一次下齐 · 全部离线可用 · 无追踪无广告下面 8 个安装包全部来自本账号各仓库的 GitHub Release, 版本号、体积、发布时间都是构建时从 Release 元数据里取的,不是写死的文案。 没有广告 SDK、没有追踪、没有账号体系——这一点和它们本来的实现一致。
可安装应用(8)
不是安装包(4)
这几个是脚本、服务端或纯静态站,本来就没有 APK。放进商店页只是为了让「账号里有什么」一眼看全, 按钮指向仓库,不伪造一个包。
装不上 / 下载被拦住了怎么办
- Android 8.0 起,浏览器下载的 APK 需要先允许「安装未知应用」——在系统弹窗里点允许即可。
- 部分机型会提示「此类文件可能有害」,这是对非商店来源 APK 的通用提示,选择仍要安装。
- 如果浏览器把文件存成了
.bin或没有后缀,重命名回.apk再装。 - 关于一键下载:浏览器对同一页面连续触发的下载有限流(桌面 Chrome 会弹「允许多个下载」,移动端更严格)。所以每批 5 个,收到文件后点「继续」补齐剩下的,断在哪就从哪接着下。
- 若某个包始终下不下来,直接在列表里单独点它的下载按钮即可,效果一样。
- 校验完整性:页面上显示的体积就是 Release 里资源的字节数,下载后可自行比对。
下载速度
这里没有服务端、也没有 CDN,就是 GitHub 在发文件。能动的只有两件事: 「从哪下」和「怎么下」。两件都做了,下面把依据和取舍摊开说—— 包括一个做错了又撤掉的做法,因为它失败得太安静,不写下来下一个人会再走一遍。
① 「从哪下」:按你的地区自动选源(不用测速)
直连 GitHub 的体验是按地区两极分化的,而且这个差异是稳定的:大陆普遍只有 几百 KB/s 甚至断流,海外接近满速。既然差异稳定,就可以在本地推断,一个网络请求都不用发。
判断依据全部来自浏览器已有的本地信息:
| 信号 | 例子 | 作用 |
|---|---|---|
| 时区 | Asia/Shanghai | 主要依据 |
| 语言 / 地区 | zh-CN → CN | 辅助 |
命中 → 判定「直连大概率很慢」→ 默认启用加速;否则默认官方直连 (海外直连本来就不慢,套一层反代只是多一跳)。
「走了第三方」这件事必须看得见。上面那行状态会实时显示当前用哪个源,点「切换」就能改回官方直连, 选择会记住。加速源打不开时会显式回退到官方并在页面说明,不静默降级。 默认开加速的前提,是它完全透明。
② 为什么不「自动测速选源」:做过,是假的
最直觉的做法是用 fetch 并发探测每个候选、按实测速度挑最快的。我实现过,结果是四个候选一个都读不到数据。
原因是 CORS:GitHub Release 会 302 到 release-assets.githubusercontent.com,
而那一跳不带 Access-Control-Allow-Origin,三个反代同样不带。
浏览器读不到响应字节数,计时恒为 0。
更糟的是它看起来是能用的:探针全部失败后会悄悄退回官方直连,页面照常下完文件, 用户完全不会察觉——区别只是白花了 4 次请求,而那个「智能选源」从来没生效过。
顺带一个反直觉的点:探针 fetch 失败只说明「缺 CORS 头」,
不代表镜像挂了——实测失败的候选,用浏览器直接下照样是 200 完整文件。
所以「能不能 fetch 通」既不能当可用性判断,也不能当选源依据。
③ 「怎么下」:并行建连;但别指望「多线程下载」
这里没有「多线程下载大文件」,因为实测不成立。同一个 58.3 MB 的包, 在同一个网络里开不同数量的并发连接:
| 并发连接 | 总吞吐 | 用时 |
|---|---|---|
| 1 条 | 6.25 MB/s | 14.8 s |
| 4 条(分块下载) | 5.98 MB/s | 9.8 s |
每条连接的吞吐是固定的,多开连接不增加总带宽,所以分块下载写上去只是好看,不会变快。
但并行发起多个包是真实收益——因为小包慢在建连,不是慢在带宽:
| 安装包 | 体积 | 单连接实测 |
|---|---|---|
| iceScribe | 58.3 MB | 2.4 MB/s |
| 魔搭模型库 | 7.8 MB | 2.1 MB/s |
| MusicFusion | 0.3 MB | 1.3 MB/s |
| iceBrowser | 0.17 MB | 0.9 MB/s |
| KayaGo | 0.07 MB | 0.78 MB/s |
小包的 TTFB 实测 0.3~1.3 秒,包越大这部分占比越小。所以页面每批并行发起 5 个: 总吞吐是几条连接之和,而不是把 5 次建连的等待串起来。
④ 修复「下载慢 / 链接经常失效」:多源轮转 + 换源重下
先说清楚一件事:页面没法自动知道哪个包有没有下成。
下载走的是 <a> 导航,而跨域读响应被 CORS 挡死——
直连和三个反代都不带 Access-Control-Allow-Origin,
no-cors 只能拿到 opaque response(status=0、type=opaque,字节数读不到)。
实测确认:无论包是否存在、源是否超时,fetch 都在 10~20 ms 内返回,读不出任何差异。
所以「自动重试」在浏览器里是做不到的,任何声称能做的实现都是在骗人。
那能做什么?两件真事:
① 不再把所有包押在一个源上。之前 8 个包全用同一个源,一个反代限速就全灭。
现在按包轮转分摊到多个加速源,单源挂掉最多影响其中一两个。
实测就有反例:ghproxy.net 在 61 MB 包上 3/3 次都下不完
(3 分钟只拿到 3~4 MB),这种源已经被移出候选——留在列表里,
一旦被选中,用户看到的就是「链接失效」。
② 每个包都能单独「换源重下」。某个包没下来,点它右边的按钮, 会换到下一个候选源立即重下,不用整批重来。源的状态就写在每个包旁边。
| 下载源 | 角色 | 地址前缀 |
|---|---|---|
| GitHub 官方 | 兜底 | (直连,无前缀) |
| gh-proxy.com | 加速 | https://gh-proxy.com/ |
| ghfast.top | 加速 | https://ghfast.top/ |
这张表来自仓库里的 data/mirrors.py,是构建时渲染的——不是写死在本页里的。
某个镜像挂掉了,删掉那一行就好,前端会自动少一个候选;direct 这条不允许删,它是兜底。