Obtainium 源码直装指南:从 Release 直接获取 Android 应用更新
【免费下载链接】ObtainiumGet Android app updates straight from the source.项目地址: https://gitcode.com/GitHub_Trending/ob/Obtainium
本文以仓库根目录 README.md 为骨架,结合 lib/ 源码与 docs/DEVELOPER_GUIDE.md 展开。
Obtainium 是一款以"Get Android app updates straight from the source"(直接从源头获取 Android 应用更新)为核心设计理念的 Flutter 应用:它绕过传统应用商店,直接从各类应用源(如 GitHub、GitLab、F-Droid 仓库、APK 站点、甚至任意 HTML 页面)的 Release 页面获取最新版本,完成 APK 下载与安装,并在新版本发布时向你推送通知。读完本文,你将掌握:Obtainium 支持哪些应用源及其分类、如何查找并导入社区共享的 App 配置、如何从 GitHub / F-Droid / IzzyOnDroid 安装 Obtainium 并验证其签名,以及源码层面这套"源 → 版本探测 → 过滤 → 安装"流水线的工作机理。
设计理念:为什么需要"直连源头"的应用更新器
传统应用分发依赖中央商店作为唯一入口,而开源与独立开发者生态中,大量应用的官方发布渠道其实是其自身主页上的 Release 页面或 APK 直链。Obtainium 的设计目标就是把这些分散的"源头"统一成可追踪、可更新、可通知的清单,让用户始终拿到开发者亲手发布的构建产物。
从仓库源码看,这一理念在架构上体现为高度抽象的源(AppSource)扩展模型:每种应用源对应 lib/app_sources/ 目录下的一个 Dart 文件,全部继承自 lib/providers/source_provider.dart 中的抽象基类AppSource。开发指南 docs/DEVELOPER_GUIDE.md 明确写道:"这是 Obtainium 的核心可扩展性模型——要支持一个新的应用源,只需在lib/app_sources/中新增一个文件,并在SourceProvider._buildSources()中注册。"
支持的应用源全览
README 将当前支持的应用源分为四大类,逐一整理如下(均可对照源码逐一核实):
开源项目通用源
| 源 | 源码实现 |
|---|---|
| GitHub | lib/app_sources/github.dart |
| GitLab | lib/app_sources/gitlab.dart |
| Forgejo(含 Codeberg) | lib/app_sources/codeberg.dart |
| F-Droid | lib/app_sources/fdroid.dart |
| 第三方 F-Droid 仓库 | lib/app_sources/fdroidrepo.dart |
| IzzyOnDroid | lib/app_sources/izzyondroid.dart |
| SourceHut | lib/app_sources/sourcehut.dart |
其他通用源
| 源 | 源码实现 |
|---|---|
| APKPure | lib/app_sources/apkpure.dart |
| Aptoide | lib/app_sources/aptoide.dart |
| Uptodown | lib/app_sources/uptodown.dart |
| itch.io | lib/app_sources/itchio.dart |
| Huawei AppGallery | lib/app_sources/huaweiappgallery.dart |
| Tencent App Store | lib/app_sources/tencent.dart |
| vivo App Store(中国) | lib/app_sources/vivoappstore.dart |
| RuStore | lib/app_sources/rustore.dart |
| Farsroid | lib/app_sources/farsroid.dart |
| Samsung Galaxy Store | lib/app_sources/samsunggalaxystore.dart |
| LiteAPKs | lib/app_sources/liteapks.dart |
| APK4Free | lib/app_sources/apk4free.dart |
| CoolApk | lib/app_sources/coolapk.dart |
| SourceForge | lib/app_sources/sourceforge.dart |
| Jenkins Jobs | lib/app_sources/jenkins.dart |
| APKMirror(仅追踪 Track-Only) | lib/app_sources/apkmirror.dart |
| APKCombo | lib/app_sources/apkcombo.dart |
| RockMods(仅追踪 Track-Only) | lib/app_sources/rockmods.dart |
特定应用专用源
| 源 | 源码实现 |
|---|---|
| Telegram App | lib/app_sources/telegramapp.dart |
| Neutron Code | lib/app_sources/neutroncode.dart |
兜底源(Fallback)
- Direct APK Link(直接 APK 链接):lib/app_sources/direct_apk_link.dart。
- "HTML"(兜底):任何返回包含 APK 文件链接的 HTML 页面的 URL 都可以作为源,实现在 lib/app_sources/html.dart。
从源码结构可以推断,SourceProvider在解析用户输入 URL 时先按 host 正则匹配各具名源,最后才回退到HTML这个"万能兜底",因此 HTML 源永远排在匹配顺序的最后(参见 lib/providers/source_provider.dart 附近_buildSources()与getSource()的注册与解析逻辑)。
寻找现成的 App 配置(Finding App Configurations)
为某个应用手动配置源参数有时比较繁琐,因此 README 提供了三条获取现成配置的途径:
- 社区共享配置站:在 crowdsourced 配置站上直接搜索应用,找到即可一键导入。
- 提交配置请求:若找不到所需应用,可到该配置站的 issues 页面留言请求补充。
- 贡献配置:通过向该配置站仓库发起 PR 的方式,把你配置好的应用参数贡献给社区。
这些共享配置本质上就是仓库源码中App模型的 JSON 序列化形态。在 lib/providers/source_provider.dart 中,App.toJson()会输出id(Android 包名或临时哈希)、url、author、name、installedVersion、latestVersion、apkUrls、preferredApkIndex、additionalSettings(每个应用的源专属参数)等字段;反向的App.fromJson()则先执行appJSONCompatibilityModifiers()这一串幂等迁移函数,保证旧版配置在升级后仍可加载(该迁移逻辑被 try/catch 包裹,单个迁移失败不会导致整个加载流程中断)。
安装 Obtainium 与签名验证
README 提供了三个分发渠道的安装方式,均需从设备浏览器/下载器获取 APK 后手动安装:
- GitHub Releases:从项目 Releases 页面下载 APK。
- IzzyOnDroid 仓库:IzzyOnDroid 是知名的开源应用镜像仓库,可通过其 F-Droid 索引页安装。
- F-Droid 官方仓库:注意 F-Droid 渠道安装的是
dev.imranr.obtainium.fdroid这个独立包名的构建风味(flavour)。从源码看,该风味使用独立的入口 lib/main_fdroid.dart,并在 lib/main.dart 中通过bool isFdroidBuild = false;这一全局变量区分:普通构建为false,F-Droid 构建在main_fdroid.dart中被置为true。两者行为差异主要体现在首次运行时是否自动添加"Obtainium 自更新"条目(lib/main.dart 中if (!isFdroidBuild)分支)。
验证信息(Verification info)
为防范供应链攻击,README 给出了两套校验依据:
| 项目 | 值 |
|---|---|
| 包名(Package ID) | dev.imranr.obtainium |
| 签名证书 SHA-256 哈希 | B3:53:60:1F:6A:1D:5F:D6:60:3A:E2:F5:0B:E8:0C:F3:01:36:7B:86:B6:AB:8B:1F:66:24:3D:A9:6C:D5:73:62 |
| 签名适用范围 | 上述签名同样适用于 F-Droid 风味,得益于可复现构建(reproducible builds) |
| PGP 公钥 | 用于验证 APK 哈希,可在 Ubuntu keyserver 上以contact@imranr.dev检索 |
也就是说:无论从 GitHub 还是 F-Droid 渠道安装,只要签名证书 SHA-256 一致,即可确认为同一发布者的产物。仓库中 docker/Dockerfile 与 sign.sh 的存在也从工程层面印证了可复现构建与签名流程是该项目的基础设施组成部分。
局限性(Limitations)
README 明确提示了唯一一条核心局限,需要用户理解:
对于某些源,数据是通过Web scraping(网页抓取)获取的,一旦网站改版,抓取逻辑很容易失效;此时可能没有更可靠的替代方法可用。
这条局限在源码中有充分印证。以 lib/app_sources/html.dart 的grabLinksCommon()为例:该函数用html包解析页面中的<a>标签、正则提取 URL、按customLinkFilterRegex正则过滤、用compareAlphaNumeric做智能排序,最后再交给AppSource.isApkOrContainerFile()判定是否为可安装的容器文件(.apk/.xapk/.apkm/.apks等)。这类依赖页面 DOM 结构与链接命名规律的做法,天然对网站改版敏感。README 的这句警告正是对这种实现方式的开诚布公。
从源码看"直连源头"的核心流水线
为帮助读者深入理解,这里将 README 概述的功能映射到具体实现链路(对应 docs/DEVELOPER_GUIDE.md 中的架构说明):
1. URL 标准化与源解析
用户粘贴任意 URL 后,SourceProvider.getSource(url)会先尝试按 host 正则匹配已注册的源,失败则回退到 HTML 源。每个源的sourceSpecificStandardizeURL()负责把 URL 归一化为规范形态(canonical form),否则抛出InvalidURLError。例如 GitHub 源通过standardizeUrlWithRegex把输入约束为https://github.com/{owner}/{repo}形式(见 lib/app_sources/github.dart)。
2. 最新版本探测
抽象基类定义了核心契约方法getLatestAPKDetails(standardUrl, additionalSettings),返回统一的APKDetails(版本号、APK URL 列表、应用名、发布日期、更新日志、全部资产 URL)。以 GitHub 源为例,它调用 GitHub REST API(/repos/{owner}/{repo}/releases?per_page=100),并支持一系列细粒度选项(见 lib/app_sources/github.dart 的表单项定义):
includePrereleases:是否包含预发布版本;fallbackToOlderReleases:最新版无可用 APK 时是否回退到更早的 Release;filterReleaseTitlesByRegEx/filterReleaseNotesByRegEx:按标题/正文正则过滤;verifyLatestTag:是否单独请求/releases/latest校验最新 tag;sortMethodChoice:排序方式(按日期date、智能名称smartname、不排序none、smartname-datefallback或纯名称name,默认date);releaseTitleAsVersion:用 Release 标题而非 tag 作为版本号。
3. 版本与 APK 过滤
拿到候选 APK 列表后,getApp()会依次应用:versionExtractionRegEx(版本号提取正则,通过extractVersion实现)、apkFilterRegEx(APK 文件名过滤正则,支持invertAPKFilter取反)、autoApkFilterByArch(按设备supportedAbis自动按架构过滤,实现在 lib/providers/source_provider.dart)。这些键全部来自AppSource._commonAppSettingFormItems(见 lib/providers/source_provider.dart),属于所有源共用的逐应用设置项。
4. 更新检查与后台任务
前台下拉刷新走 lib/providers/apps_provider_updates.dart 的checkUpdates():它以固定并发上限(kDefaultFetchConcurrency = 4)分批拉取各应用的新元数据,并每隔约 3 秒批量saveApps()一次,从而把 UI 重建次数从 O(N) 降到 O(N/批)。后台更新则通过workmanager注册 15 分钟最小周期的定时任务(见 lib/main.dart 的_scheduleWorkManager()),由带@pragma('vm:entry-point')注解的callbackDispatcher()无头执行bgUpdateCheck()。
5. 安装策略
下载完成后,lib/installers/ 目录下的策略模式抽象决定如何安装:默认StockInstaller(走 Android PackageInstaller 会话 API),检测到 Shizuku/Dhizuku/Sui 时用ShizukuInstaller(也用于 Obtainium 自我更新),用户也可指定ExternalInstaller转交第三方安装器(详见 docs/DEVELOPER_GUIDE.md 的安装器对照表)。
关键设置项速查(源码级默认值)
以下设置项在 lib/providers/settings_provider.dart 中有明确的类型与默认值,方便配置时对照:
| 设置键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
updateInterval | int | 360(分钟) | 前台自动检查更新的间隔 |
updateIntervalSliderVal | double | 6.0 | 设置页滑块的中间值 |
checkOnStart | bool | false | 启动时检查更新 |
enableBackgroundUpdates | bool | true | 是否启用后台更新 |
bgUpdatesOnWiFiOnly | bool | false | 后台更新仅在 Wi-Fi 下进行 |
bgUpdatesWhileChargingOnly | bool | false | 后台更新仅在充电时进行 |
enableCertificatePinning | bool | false | 是否启用证书固定(配合 assets/ca-certs/ 中的根证书) |
theme | int | system | 主题:system / light / dark |
themeColor | int | 0xFF6438B5 | 主题色,默认紫色 |
colourSchemeMode | enum | standard | 配色方案:standard / vibrant / expressive / materialYou |
useBlackTheme | bool | false | 深色主题是否使用纯黑背景 |
groupBy | enum | none | 应用列表分组方式:none / category / source |
hideDowngrades | bool | true | 是否隐藏版本回退提示 |
onlyCheckInstalledOrTrackOnlyApps | bool | false | 只检查已安装或 Track-Only 的应用 |
此外,逐应用的additionalSettings中还包含minimumUpdateAgeDays(更新最小发布年龄,供应链延迟策略,可选值为 0/1/2/3/5/7/14/30 天,0 表示使用全局默认,见 lib/providers/source_provider.dart)、trackOnly(仅追踪不更新)、versionDetection(版本探测开关)等通用选项。
结语
Obtainium 用一套简洁的"源抽象 + 配置驱动"架构,把"从源头获取更新"这一朴素诉求变成了可扩展的应用源生态。对普通用户而言,它提供了一条绕过商店、直达开发者 Release 页面的更新通道,并配以共享配置站与可复现构建签名来降低使用门槛;对开发者而言,lib/app_sources/ 中 30+ 个源实现、AppSource基类与SourceProvider单例构成了一个边界清晰、易于扩展的参考范例。若需深入了解内部机制,可继续阅读 docs/DEVELOPER_GUIDE.md 与 lib/ 源码。
【免费下载链接】ObtainiumGet Android app updates straight from the source.项目地址: https://gitcode.com/GitHub_Trending/ob/Obtainium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考