Skip to content

Repository files navigation

Novi

面向非 Google Play 分发 Android 应用的轻量、安全自更新模块。

简体中文 | English

流水线 Android 9+ Kotlin 许可证

功能特性 | 快速开始 | 更新源 | Windows 托管 | 安全模型 | 文档

Note

Novi 由 AlfWorks 开发。此 GitHub 仓库是其权威 GitLab 仓库的公开镜像。

Novi is developed under AlfWorks. This GitHub repository is a public mirror of the canonical GitLab repository.

Important

Novi 0.1.1 已发布到 Maven Central。

Novi 负责从验证已签名的发布清单开始,完成版本检查、APK 下载与验证,并将安装交给 Android 系统安装器。宿主应用始终负责决定检查时机、管理界面,并取得用户明确同意。

Core 仅依赖 Android 平台与 Kotlin 标准库。独立的 Compose 模块提供可选的 Material 3 状态驱动对话框;仓库还附带一个零第三方依赖的 Windows 更新源托管程序。

功能特性

  • 对发布清单原始字节进行 P-256 分离签名验证。
  • 有优先级的多更新源,支持故障转移、镜像或不同发布轨道。
  • 流式下载 APK,同时强制校验文件大小与 SHA-256。
  • 验证应用包名、版本号与 APK 签名证书。
  • 集成 Android PackageInstaller,支持进程被替换后的安装状态恢复。
  • 无安装应用权限时,安全回退到手动浏览器下载。
  • 可选 Material 3 更新对话框,内置简体中文与英文资源。
  • 支持自定义网络传输层,可接入代理、证书固定或宿主网络栈。
  • 可使用 GitLab、对象存储、普通 Web 服务器或附带的 Windows 托管程序。

Novi 不提供静默安装、后台界面、发布私钥管理、差分更新或应用生命周期框架。

模块

模块 用途
novi-core 清单验证、更新检查、下载、APK 验证与安装。
novi-compose 可选的状态驱动 Material 3 更新对话框。
sample 用于设备与界面验证的集成示例。
windows-host 兼容 Windows 的只读更新源与原子发布工具。
consumer-test 以外部使用者身份验证暂存 Maven 制品的独立工程。

工作原理

latest.json + 分离签名
          |
          v
   使用受信任 P-256 公钥验证
          |
          v
      比较 versionCode
          |
          v
 从选定更新源下载 APK ------> 按顺序尝试其他更新源
          |
          v
 大小 + SHA-256 + 包名 + 版本 + 签名者验证
          |
          v
 Android PackageInstaller ----> 系统安装确认
          |
          +--------------------> 无安装权限时手动浏览器下载

每个更新源都是一个静态目录:

latest.json
latest.json.sig
artifacts/<version>/app.apk

快速开始

从 Maven Central 添加 Novi(novi-compose 可选):

implementation("com.alphynia.novi:novi-core:0.1.1")
implementation("com.alphynia.novi:novi-compose:0.1.1") // 可选

在 Application 作用域创建一个 Novi 实例:

val novi = Novi(
    NoviConfig(
        context = applicationContext,
        applicationId = BuildConfig.APPLICATION_ID,
        currentVersionCode = BuildConfig.VERSION_CODE.toLong(),
        sources = listOf(
            HttpUpdateSource(
                id = "primary",
                rootUrl = URL("https://updates.example.com/my-app/stable/"),
            ),
            HttpUpdateSource(
                id = "fallback",
                rootUrl = URL("https://gitlab.example.com/my-app/updates/"),
            ),
        ),
        manifestKeys = mapOf(
            "manifest-2026" to NoviKeys.p256PublicKey(
                BuildConfig.NOVI_MANIFEST_PUBLIC_KEY,
            ),
        ),
        allowedApkSigners = setOf(BuildConfig.NOVI_APK_SIGNER_SHA256),
    ),
)

从 Application 级协调器调用 checkOncePerProcess。检测到新版本后,等 Activity 进入前台,再依次执行 download -> verify -> install。Novi 不会自行启动界面。

如果应用不能请求安装软件包,Novi 会返回 ManualInstallRequired。宿主应向用户解释手动流程,并只在用户选择继续后打开其中经过签名约束的制品地址。Novi 不会请求用户授予安装权限,也不会在权限变化后自动重试安装。

完整流程和生命周期规则请参阅集成指南API 约定

更新源

Novi 按配置顺序检查更新源,并采用遇到的第一份签名有效清单。这是有意设计:优先源可以提供内测、地区、企业或其他特殊版本轨道,后续源则作为稳定版本或故障回退。

APK 首先从提供所选清单的更新源下载。如果下载失败,Novi 会使用完全相同的已签名相对路径依次尝试其他更新源。无论文件来自哪里,都必须通过应用本地信任的清单公钥和 APK 签名者策略。

除本机回环开发源外,Novi 强制使用 HTTPS。它不会跟随跨源重定向,也不会削弱 TLS 主机名验证。

准备更新

生成 P-256 清单密钥,并将私钥保存在仓库之外:

openssl ecparam -name prime256v1 -genkey -noout -out manifest-private.pem
openssl ec -in manifest-private.pem -pubout -out manifest-public.pem

为发布 APK 生成并签署清单:

python scripts/prepare_release.py \
  --apk app-release.apk \
  --application-id com.example.app \
  --version-code 42 \
  --version-name 1.4.0 \
  --artifact-path artifacts/42/app-release.apk \
  --key-id manifest-2026 \
  --private-key manifest-private.pem \
  --output release

发布顺序必须是不可变 APK、latest.json.sig,最后才是 latest.json。附带的 Windows 发布工具会以原子操作保证这个顺序。

Windows 托管

可选托管程序仅使用 Python 标准库,并提供与 GitLab 或其他静态 HTTPS 源相同的 Novi 协议。它支持 GETHEAD、Range 断点下载、安全缓存头、路径限制和健康检查。

.\windows-host\run.ps1 `
  -Root D:\NoviSources `
  -ListenAddress 127.0.0.1 `
  -Port 8080

发布一个应用的更新:

python .\windows-host\publish_source.py `
  --release .\release `
  --apk .\app-release.apk `
  --root D:\NoviSources\my-app

应通过 IIS、Caddy 或 nginx 等反向代理提供 HTTPS。HTTP 托管进程只需读取权限,发布操作应使用单独的写入身份。运维细节参阅 Windows 托管文档

安全模型

Novi 使用两个彼此独立的信任层:

  1. 清单密钥验证发布元数据与预期制品哈希。
  2. APK 签名证书验证可执行应用代码。

APK 签名者白名单内置于宿主应用,远程元数据无法扩大其范围。安装前,Novi 会验证 APK 大小、SHA-256、应用 ID、版本号、签名证书,以及写入安装会话的准确字节。

部署前请阅读完整的安全模型。请勿在公开 Issue 中提交私钥、生产清单或敏感应用数据。

构建与测试

环境要求:

  • JDK 17
  • Android SDK 36
  • 仓库内附带的 Gradle Wrapper
  • 发布工具需要 Python 3.10+ 与 OpenSSL

运行主要检查:

./gradlew :novi-core:testDebugUnitTest \
  :novi-core:lintRelease \
  :novi-compose:lintRelease \
  :sample:assembleDebug

python3 scripts/test_prepare_release.py
python3 scripts/test_windows_host.py
python3 scripts/test_windows_publish.py

在不向外部仓库发布的情况下生成 Maven 兼容暂存制品:

./gradlew \
  :novi-core:publishMavenPublicationToStagingRepository \
  :novi-compose:publishMavenPublicationToStagingRepository

CI 还会让 consumer-test 通过这些暂存 Maven 坐标构建,以发现发布元数据与传递依赖错误。

文档

文档按职责分区,索引参见 docs/README.md。能力的权威清单是能力矩阵

参与贡献

V1 成型期间,欢迎提交问题报告和范围明确的合并请求。行为变更应说明受影响的信任边界、失败模式和兼容性影响。请保持 Core 轻量;只有收益明显高于长期成本时,才应增加新的运行时依赖。

提交改动前,请运行相关单元测试、Lint、发布工具测试与外部 Maven 消费构建。

许可证

Novi 使用 Apache License 2.0 开源。归属信息参阅 NOTICE

About

A lightweight, secure, multi-source self-update framework for Android applications.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages