GeneralUpdate.Avalonia.Android
命名空间: GeneralUpdate.Avalonia.Android | 主要入口: GeneralUpdateBootstrap.CreateDefault() | NuGet 包: GeneralUpdate.Avalonia.Android
1. 组件简介
1.1 组件概述
GeneralUpdate.Avalonia.Android 是面向 Avalonia 应用的 Android 平台自动更新组件,专为 Android APK 的更新场景设计。它提供版本对比、可断点续传的 APK 下载、SHA256 完整性校验、以及 Android Package Installer 自动启动的全流程编排能力。
Android 平台的更新与桌面应用不同:APK 安装必须通过 Android 系统安装器完成,下载过程可能被用户中断或切换网络,安装前需要检查 "安装未知应用" 权限。该组件封装了这些平台差异,让 Avalonia 开发者只需提供更新包信息即可完成更新。
核心能力:
| 能力 | 说明 |
|---|---|
| 版本对比 | 内置 SystemVersionComparer,通过 IVersionComparer 接口支持自定义版本策略 |
| 断点续传下载 | HttpResumableApkDownloader 支持 HTTP Range 请求头,中断后可续传 |
| SHA256 完整性 校验 | 下载完成后自动计算文件 SHA256,与服务端声明的哈希值比对,防止文件损坏或篡改 |
| APK 安装编排 | 通过 AndroidApkInstaller 调用系统 Package Installer,自动处理 FileProvider URI |
| HTTP 传输配置 | HttpDownloadOptions 支持 SSL/TLS 证书策略、代理、超时、重试和多种认证方案 |
| 多协议认证 | 支持 HMAC-SHA256、Bearer Token、API Key、HTTP Basic 四种认证方案,支持全局和单包粒度 |
| 事件通知 | 版本发现、下载进度、完成、失败等事件通知 |
| 状态快照 | GetSnapshot() 随时获取当前更新状态、失败原因和消息 |
| UI 线程调度 | IUpdateEventDispatcher 支持将事件调度到 UI 线程(如 Avalonia 的 SynchronizationContext) |
| 渐进式下载 | 临时文件 .part 和 Sidecar .json 机制,记录已完成字节数,支持进程级断点续传 |
解决的业务痛点:
- Avalonia 应用发布 Android 版本后,需要可靠的内置更新能力,但 Android APK 安装必须经由系统安装器
- 下载大 APK 包时可能被用户中断、网络切换,需要断点续传能力降低重复下载流量
- 需要对下载的 APK 进行完整性校验,防止传输损坏或被篡改
- 需要灵活的认证方案对接不同服务端的鉴权要求
Android 平台不能像桌面端那样直接替换文件。APK 必须通过 Android Package Installer 安装,系统会处理签名验证、权限授予和应用替换。本组件封装了这些平台差异,但 APK 签名、版本号递增等仍需要你在构建流水线中保证。
业务使用场景:
- Avalonia 跨平台应用的 Android APK 自动更新
- 企业内部 Android 应用的静默或引导式更新
- 需要通过 CDN / OSS 分发 APK 包的场景
1.2 环境与依赖
| 项目 | 说明 |
|---|---|
| NuGet 包 | GeneralUpdate.Avalonia.Android |
| 目标框架 | net10.0-android(最低 Android API 26+) |
| 依赖包 | Xamarin.AndroidX.Core(FileProvider 支持) |
| 兼容性 | Android 8.0 (API 26) 及以上版本 |
2. 组件功能列表
| 功能名称 | 功能描述 | 类型 | 是否必填 | 备注限制 |
|---|---|---|---|---|
| 版本对比检查 | 比对当前版本与目标版本,判断是否有更新可用 | 基础 | 必选 | ValidateAsync,支持自定义版本比较器 |
| APK 断点续传下载 | 从服务端下载 APK 包,支持 HTTP Range 断点续传 | 基础 | 必选 | DownloadAndVerifyAsync |
| SHA256 校验 | 下载完成后自动计算 SHA256 与服务端哈希比对 | 基础 | 自动 | 通过 IHashValidator 实现 |
| APK 安装触发 | 调用 Android Package Installer 安装 APK | 基础 | 必选 | LaunchInstallerAsync |
| HTTP 传输配置 | SSL 证书校验、代理、超时、重试、认证 | 拓展 | 可选 | HttpDownloadOptions |
| 多协议认证 | HMAC-SHA256 / Bearer / API Key / Basic | 拓展 | 可选 | 全局或单包粒度配置 |
| 进度通知 | 下载进度(速度、字节数、百分比) | 基础 | 可选 | AddListenerDownloadProgressChanged |
| 完成通知 | 版本发现、下载完成、安装完成事件 | 基础 | 可选 | AddListenerUpdateCompleted |
| 失败通知 | 失败原因、异常信息、失败包信息 | 基础 | 可选 | AddListenerUpdateFailed |
| 验证通知 | 发现可用更新时触发 | 基础 | 可选 | AddListenerValidate |
| 状态快照 | 随时获取当前更新状态 | 拓展 | 可选 | GetSnapshot() |
| UI 线程调度 | 自定义事件调度策略 | 拓展 | 可选 | 实现 IUpdateEventDispatcher |
| 自定义下载器 | 自定义下载实现 | 拓展 | 可选 | 实现 IUpdateDownloader |
| 自定义哈希验证 | 自定义哈希算法 | 拓展 | 可选 | 实现 IHashValidator |
| 自定义版本比较 | 自定义版本对比逻辑 | 拓展 | 可 选 | 实现 IVersionComparer |
| 自定义 APK 安装器 | 自定义安装实现 | 拓展 | 可选 | 实现 IApkInstaller |
| 自定义文件存储 | 自定义文件读写实现 | 拓展 | 可选 | 实现 IFileStorage |
| 自定义 SSL 策略 | 自定义 HTTPS 证书校验 | 拓展 | 可选 | 实现 ISslValidationPolicy |
| 自定义 HTTP 认证 | 自定义 HTTP 请求认证 | 拓展 | 可选 | 实现 IHttpAuthProvider |
3. API 配置说明
3.1 配置字段(属性 Props)
AndroidUpdateOptions:
| 字段名 | 数据类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
DownloadDirectoryPath | string | ""(自动使用 CacheDir/update 或 TempPath/update) | 可选 | 下载文件存放目录,为空时自动选择 |
FileProviderAuthority | string | "" | 是 | Android FileProvider authority,需与 AndroidManifest 配置一致 |
TemporaryFileExtension | string | ".part" | 可选 | 临时下载文件扩展名 |
SidecarExtension | string | ".json" | 可选 | 断点续传元数据文件扩展名 |
DownloadBufferSize | int | 65536(64 KB) | 可选 | 下载缓冲区大小(字节) |
SpeedSmoothingWindowSeconds | int | 4 | 可选 | 下载速度平滑窗口(秒) |
HttpDownloadOptions:
| 字段名 | 数据类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
SslValidationPolicy | ISslValidationPolicy? | null | 可选 | 自定义 SSL 证书验证策略;null 使用系统默认 |
RequestTimeout | TimeSpan | 30s | 可选 | 单次 HTTP 请求超时 |
DownloadTimeout | TimeSpan | 10min | 可选 | 整体下载操作超时 |
Proxy | IWebProxy? | null | 可选 | HTTP 代理 |
UseProxy | bool | false | 可选 | 是否启用配置的代理 |
MaxRetryAttempts | int | 3 | 可选 | 最大重试次数(3 表示初始 1 次 + 2 次重试) |
RetryBaseDelay | TimeSpan | 1s | 可选 | 指数退避基本延迟:baseDelay * 2^attempt |
AuthProvider | IHttpAuthProvider? | null | 可选 | 全局 HTTP 认证提供器,单包认证优先级更高 |
UpdatePackageInfo:
| 字段名 | 数据类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
Version | string | — | 是 | 目标版本号 |
DownloadUrl | string | — | 是 | APK 下载地址 |
Sha256 | string | — | 是 | APK 的 SHA256 哈希值,用于完整性校验 |
FileSize | long | 0 | 可选 | APK 文件大小(字节) |
FileName | string? | null | 可选 | 下载后的文件名 |
IsForced | bool | false | 可选 | 是否强制更新 |
VersionName | string? | null | 可选 | 版本展示名称 |
Description | string? | null | 可选 | 版本描述 |
PublishTime | DateTimeOffset? | null | 可选 | 发布时间 |
AuthScheme | AuthScheme? | null | 可选 | 单包认证方案,优先于全局配置 |
AuthToken | string? | null | 可选 | Bearer 或 API Key 认证令牌 |
AuthSecretKey | string? | null | 可选 | HMAC-SHA256 签名密钥 |
BasicUsername | string? | null | 可选 | HTTP Basic 用户名 |
BasicPassword | string? | null | 可选 | HTTP Basic 密码 |
UpdateState 枚举:
| 枚举值 | 数值 | 说明 |
|---|---|---|
None | 0 | 初始状态 |
Checking | 1 | 正在检查更新 |
UpdateAvailable | 2 | 发现可用更新 |
Downloading | 3 | 正在下载 |
Verifying | 4 | 正在校验 |
ReadyToInstall | 5 | 准备安装 |
Installing | 6 | 正在安装 |
Completed | 7 | 更新完成 |
Failed | 8 | 更新失败 |
Canceled | 9 | 已取消 |
AuthScheme 枚举:
| 枚举值 | 说明 |
|---|---|
Hmac | HMAC-SHA256 签名认证 |
Bearer | Bearer Token 认证 |
ApiKey | API Key 认证 |
Basic | HTTP Basic 认证 |
3.2 实例方法
GeneralUpdateBootstrap(静态工厂):
| 方法名 | 入参明细 | 使用场景 | 注意事项 |
|---|---|---|---|
CreateDefault(AndroidUpdateOptions, ...) | options — 更新选项;可选参数:contextProvider, activityProvider, httpClient, versionComparer, eventDispatcher, logger, httpOptions | 创建默认的 Android 更新引导实例 | 所有可选参数为 null 时使用内置默认实现 |
IAndroidBootstrap:
| 方法名 | 入参明细 | 使用场景 | 注意事项 |
|---|---|---|---|
ValidateAsync(UpdatePackageInfo, string, CancellationToken) | packageInfo — 更新包信息;currentVersion — 当前版本;ct — 取消令牌 | 检查是否有可用的更新 | 返回 UpdateCheckResult,包含 UpdateFound 和 TargetVersion |
DownloadAndVerifyAsync(UpdatePackageInfo, CancellationToken) | packageInfo — 更新包信息;ct — 取消令牌 | 下载 APK 并校验 SHA256 | 返回 UpdateOperationResult,成功时 FilePath 为 APK 路径 |
LaunchInstallerAsync(UpdatePackageInfo, string, CancellationToken) | packageInfo — 更新包信息;apkFilePath — APK 文件路径;ct — 取消令牌 | 启动 Android Package Installer | 需要 FileProvider authority 配置正确 |
GetSnapshot() | 无 | 获取当前更新状态快照 | 返回 UpdateStateSnapshot(State, FailureReason, Message) |
Dispose() | 无 | 释放下载器等资源 | — |
3.3 回调事件
| 事件名称 | 回调参数 | 触发时机 | 使用说明 |
|---|---|---|---|
AddListenerValidate | ValidateEventArgs — PackageInfo, CurrentVersion | 版本对比完成后,发现可用更新时触发 | 可用于 UI 展示新版本信息 |
AddListenerDownloadProgressChanged | DownloadProgressChangedEventArgs — ProgressPercentage, DownloadSpeedBytesPerSecond, DownloadedBytes, RemainingBytes, TotalBytes, PackageInfo, StatusDescription | 下载进度更新时 | 可用于进度条展示 |
AddListenerUpdateCompleted | UpdateCompletedEventArgs — Result(UpdateOperationResult) | 下载完成或安装完成时 | 可用于 UI 切换 |
AddListenerUpdateFailed | UpdateFailedEventArgs — Result(UpdateOperationResult) | 任何阶段失败时 | 包含失败原因和异常信息 |
4. 扩展示例(高阶用法)
4.1 组件可扩展能力总览
所有服务均可通过 CreateDefault 的可选参数替换:
| 接口 | 默认实现 | 说明 |
|---|---|---|
IVersionComparer | SystemVersionComparer | 版本对比策略 |
IUpdateDownloader | HttpResumableApkDownloader | APK 下载实现 |
IHashValidator | Sha256HashValidator | SHA256 哈希校验 |
IApkInstaller | AndroidApkInstaller | APK 安装触发 |
IFileStorage | PhysicalFileStorage | 文件存储操作 |
IUpdateEventDispatcher | ImmediateEventDispatcher | 事件调度器(直接调用) |
IUpdateLogger | NoOpUpdateLogger | 日志记录器 |
IAndroidContextProvider | DefaultAndroidContextProvider | Android Context 提供器 |
IAndroidActivityProvider | NullAndroidActivityProvider | Android Activity 提供器 |
ISslValidationPolicy | 通过 HttpDownloadOptions 配置 | SSL 证书验证策略 |
IHttpAuthProvider | 通过 HttpDownloadOptions 或单包配置 | HTTP 认证提供器 |
4.2 分场景示例
场景 1:自定义版本比较策略
【场景说明】应用使用 year.month.day.build 格式版本号,默认的 System.Version 解析会失败,需要自定义版本比较器。
【示例代码】
using GeneralUpdate.Avalonia.Android.Abstractions;
public sealed class CustomDateVersionComparer : IVersionComparer
{
public bool TryCompare(string currentVersion, string targetVersion,
out int compareResult, out string? errorMessage)
{
try
{
var current = ParseVersion(currentVersion);
var target = ParseVersion(targetVersion);
compareResult = target.CompareTo(current);
errorMessage = null;
return true;
}
catch (Exception ex)
{
compareResult = 0;
errorMessage = ex.Message;
return false;
}
}
private static DateTime ParseVersion(string version) =>
DateTime.ParseExact(version, "yyyy.MM.dd.fff", null);
}
// 使用
var bootstrap = GeneralUpdateBootstrap.CreateDefault(
options,
versionComparer: new CustomDateVersionComparer());
【效果&注意事项】
- 返回的
compareResult遵循target.CompareTo(current)语义:正数表示有新版本 - 实现失败时返回
false和错误信息,引导跳过更新检查