From d82458e3bba4c2f5d7f3dde21535f21a44788fdb Mon Sep 17 00:00:00 2001 From: JusterZhu Date: Sun, 14 Jun 2026 11:44:54 +0800 Subject: [PATCH 1/3] docs: expand GeneralUpdate.Tools Mobile packaging documentation - Add technical internals: format detection (APK vs AAB), AXML binary parsing (StringPool, StartElement chunks, versionCode extraction), project build pipeline (CsprojParser, dotnet publish, artifact locate) - Add upload form field mapping table with data sources and examples - Add upload service configuration details (endpoint, auth, DPAPI) - Add 5 mobile-specific FAQ entries - Add missing Mobile section to zh-Hans i18n copy - Sync all changes to English i18n Co-Authored-By: Claude --- .../quickstart/GeneralUpdate.PacketTool.md | 55 +++++- .../quickstart/GeneralUpdate.PacketTool.md | 55 +++++- .../quickstart/GeneralUpdate.PacketTool.md | 159 +++++++++++++++++- 3 files changed, 252 insertions(+), 17 deletions(-) diff --git a/website/docs/quickstart/GeneralUpdate.PacketTool.md b/website/docs/quickstart/GeneralUpdate.PacketTool.md index 37e8511..fe86c20 100644 --- a/website/docs/quickstart/GeneralUpdate.PacketTool.md +++ b/website/docs/quickstart/GeneralUpdate.PacketTool.md @@ -30,7 +30,7 @@ dotnet run --project GeneralUpdate.Tools.csproj 前往 [GeneralUpdate.Tools Releases](https://github.com/GeneralLibrary/GeneralUpdate.Tools/releases) 下载对应平台的可执行文件,直接运行即可。 -> Simulation 模块内部会调用 `dotnet publish` 构建测试应用,因此使用仿真功能时必须安装 .NET SDK,仅运行 Patch / Extension / OSS / Config 模块则不需要。 +> Simulation 模块内部会调用 `dotnet publish` 构建测试应用,因此使用仿真功能时必须安装 .NET SDK。Mobile 模块的项目模式(Build & Locate)也会调用 `dotnet publish`,同样需要 .NET SDK。仅运行 Patch / Extension / OSS / Config 模块以及 Mobile 的文件模式则不需要。 ## 七个模块速览 @@ -373,12 +373,48 @@ Generate Sample 额外输出: ### 工具内部做了什么 1. **格式检测**:通过文件扩展名(`.apk` / `.aab`)和 ZIP 内部结构(`AndroidManifest.xml` 位置)自动识别包格式。 -2. **元数据解析**:使用 `AxmlParser` 从 ZIP 中读取二进制的 `AndroidManifest.xml`,提取 `package`、`versionName`、`versionCode`。 -3. **SHA256 计算**:对完整文件计算 SHA256 哈希值。 -4. **文件大小**:读取文件长度并格式化为人类可读的显示(KB/MB/GB)。 -5. **项目构建**(仅项目模式):调用 `dotnet publish -c Release -o {publishDir}`,自动定位输出的 APK/AAB 文件。 -6. **上传**:通过 HTTP multipart/form-data 将文件和表单字段(Name、Version、Hash、Format、Size、Platform、ProductId、IsForcibly)上传到服务端。 -7. **版本记录导出**:上传成功后生成 `mobile_version_{timestamp}.json`,包含完整的版本元数据。 + - APK 检测:打开 ZIP 文件,检查根目录是否存在 `AndroidManifest.xml`。 + - AAB 检测:打开 ZIP 文件,检查是否存在 `base/manifest/AndroidManifest.xml`。 + - 格式未知时(不是 .apk 也不是 .aab)会直接返回 Unknown。 + +2. **元数据解析**:使用 `AxmlParser` 解析二进制的 AXML(Android Binary XML)格式,从 ZIP 中读取 `AndroidManifest.xml`。解析流程如下: + - **字符串池提取**:读取 AXML 文件的 Chunk 头,找到类型为 `0x0001` 的 StringPool Chunk,从中解析出所有 UTF-16LE 编码的字符串数组。 + - **属性值提取**:遍历 XML 的 Start Element Chunk(类型 `0x0102`),解析属性块(每个属性 20 字节),通过属性名在字符串池中的索引匹配 `package` 和 `versionName`,再通过 `rawValueIndex` 从字符串池中取出属性值。 + - **versionCode 提取**:versionCode 存储为整型属性(类型 `0x10` = INT_DEC 或 `0x11` = INT_HEX),直接从属性的 `typedValueData` 字段(偏移 +16,4 字节)读取有符号整数。 + - AXML 结构与参考:https://justanapplication.wordpress.com/category/android/android-binary-xml/ + +3. **SHA256 计算**:对完整文件计算 SHA256 哈希值,输出小写十六进制字符串。 + +4. **文件大小**:读取文件长度并格式化为人类可读的显示(B / KB / MB / GB)。 + +5. **项目构建**(仅项目模式):选择 `.csproj` 后会触发: + - `MobileCsprojParser.Parse()` 解析 `.csproj` 的 XML,提取 `TargetFramework`(支持单 TFM 和多 TFM,多 TFM 时自动选取包含 `-android` 的目标框架)、`ApplicationId`(映射为 PackageName)、`ApplicationDisplayVersion`(映射为 VersionName)、`ApplicationVersion`(映射为 VersionCode)、`UseMaui`(用于识别 MAUI 项目)、`AndroidPackageFormat`、`AssemblyName`。 + - 调用 `dotnet publish "{csprojPath}" -c Release -o "{publishDir}"`。 + - 构建完成后在 `bin/Release/{tfm}/publish/` 目录搜索 `.apk` 或 `.aab` 文件,自动定位构建产物。 + - 项目类型显示:MAUI(`true`)或 Avalonia(没有 UseMaui)。 + +6. **上传**:通过 HTTP multipart/form-data 将文件上传到服务端。上传表单字段和对应的数据源如下: + + | 字段 | 值来源 | 示例 | + |------|--------|------| + | `Name` | ProductName(用户填写) | `MyApp` | + | `Version` | VersionName(自动解析) | `2.0.0` | + | `Hash` | SHA256(自动计算) | `a1b2c3d4...` | + | `Format` | 包格式(自动识别) | `.apk` / `.aab` | + | `Size` | 文件大小(自动计算) | `50000000` | + | `AppType` | 固定值 `"1"` | `1` | + | `Platform` | Platform(默认 4=Android) | `4` | + | `ProductId` | ProductId(用户填写 GUID) | `2d974e2a-...` | + | `IsForcibly` | 强制更新开关 | `true` / `false` | + + 上传服务支持以下配置: + - **Server URL**:服务端地址 + - **Upload Endpoint**:API 路径,默认 `/Packet/Create` + - **Timeout**:超时时间(秒) + - **Retry Count**:失败重试次数(指数退避) + - **Auth**:认证配置,支持 Basic / Bearer Token / API Key 三种模式(凭据通过 DPAPI 加密存储) + +7. **版本记录导出**:上传成功后自动生成 `mobile_version_{timestamp}.json`,包含完整的版本元数据。也可以在不上传的情况下单独点击 **Export Record Only** 导出记录,此时 URL 字段为 `"manual"`。 ### 输出 @@ -466,6 +502,11 @@ Generate Sample 额外输出: | Simulation 端口冲突 | 修改 `ServerPort` 或释放本地 5000 端口 | | 客户端下载后 Hash 校验失败 | 对**最终上传到 CDN/OSS 的文件**重新计算 Hash,检查是否被中间代理重压缩 | | Upgrade 进程没有启动 | 检查 `generalupdate.manifest.json` 中 `updateAppName` 和 `updatePath` 是否与发布目录结构一致 | +| Mobile 分析时提示 "Metadata extraction warning" | AXML 解析未找到预期属性,常见的两种原因:APK 使用资源 ID 引用而非直接文本存储属性值;或 APK 被加固/混淆后 AndroidManifest.xml 结构被修改。可以手动填写 PackageName、VersionName、VersionCode | +| Mobile 项目模式 Build & Locate 失败 | 确认已安装 .NET SDK 且版本支持目标框架(TFM),检查 `.csproj` 包含 `-android` 目标框架,输出目录 `bin/Release/{tfm}/publish/` 没有被写入保护 | +| Mobile 项目模式 "Build output not found" | `dotnet publish` 成功执行但未在预期目录找到 `.apk`/`.aab`。检查 `.csproj` 中 `AndroidPackageFormat` 设置是否正确(默认 `aab;apk` 优先产生 APK),以及 TFM 是否自动解析正确 | +| Mobile 上传失败 | 检查服务端地址和 Endpoint 配置是否正确,确认服务端认证方式(Basic / Bearer / API Key)与工具配置一致,查看工具日志中的 HTTP 状态码和错误消息 | +| Mobile 上传后客户端更新失败 | 确认服务端返回的版本记录 JSON 中 `Platform` 字段为 `4`(Android),`Format` 字段与客户端期望的 APK/AAB 格式一致 | --- diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md index 719e974..980b417 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md @@ -26,7 +26,7 @@ dotnet run --project GeneralUpdate.Tools.csproj Go to [GeneralUpdate.Tools Releases](https://github.com/GeneralLibrary/GeneralUpdate.Tools/releases) and download the executable for your platform. -> The Simulation module internally runs `dotnet publish` to build test apps, so you need the .NET SDK for that feature. Patch / Extension / OSS / Config / Mobile modules work without the SDK. However, Mobile's Project Mode (Build & Locate) does require the .NET SDK. +> The Simulation module internally runs `dotnet publish` to build test apps, so you need the .NET SDK for that feature. The Mobile module's Project Mode (Build & Locate) also runs `dotnet publish`, which requires the .NET SDK too. Patch / Extension / OSS / Config modules and Mobile's File Mode work without the SDK. ## Seven modules at a glance @@ -353,12 +353,48 @@ Supports two modes: ### What the tool does internally 1. **Format detection**: Identifies package format via file extension (`.apk` / `.aab`) and ZIP internal structure (AndroidManifest.xml location). -2. **Metadata parsing**: Uses `AxmlParser` to read binary `AndroidManifest.xml` from the ZIP, extracting `package`, `versionName`, `versionCode`. -3. **SHA256 computation**: Computes SHA256 hash of the full file. -4. **File size**: Reads file length and formats it for human-readable display (KB/MB/GB). -5. **Project build** (Project mode only): Runs `dotnet publish -c Release -o {publishDir}`, then auto-locates the output APK/AAB. -6. **Upload**: Sends file and form fields (Name, Version, Hash, Format, Size, Platform, ProductId, IsForcibly) via HTTP multipart/form-data. -7. **Version record export**: Generates `mobile_version_{timestamp}.json` with full version metadata after successful upload. + - APK detection: Opens the ZIP file and checks for `AndroidManifest.xml` at the root. + - AAB detection: Opens the ZIP file and checks for `base/manifest/AndroidManifest.xml`. + - If the format is neither `.apk` nor `.aab`, the detector returns Unknown. + +2. **Metadata parsing**: Uses `AxmlParser` to parse the binary AXML (Android Binary XML) format from the ZIP's `AndroidManifest.xml`. The parsing process works as follows: + - **String pool extraction**: Reads AXML chunk headers, locates the StringPool chunk (type `0x0001`), and extracts all UTF-16LE encoded strings. + - **Attribute value extraction**: Walks through Start Element chunks (type `0x0102`), parses the attribute block (20 bytes per attribute), matches attribute names by their string pool index to find `package` and `versionName`, then resolves values via `rawValueIndex` from the string pool. + - **versionCode extraction**: versionCode is stored as a typed integer attribute (type `0x10` = INT_DEC or `0x11` = INT_HEX), read directly from the `typedValueData` field (offset +16, 4 bytes) as a signed integer. + - AXML chunk structure reference: https://justanapplication.wordpress.com/category/android/android-binary-xml/ + +3. **SHA256 computation**: Computes SHA256 hash of the full file, output as a lowercase hex string. + +4. **File size**: Reads file length and formats it for human-readable display (B / KB / MB / GB). + +5. **Project build** (Project mode only): Selecting a `.csproj` triggers: + - `MobileCsprojParser.Parse()` reads the `.csproj` XML to extract `TargetFramework` (supports single and multi-TFM; auto-selects the one containing `-android`), `ApplicationId` (mapped to PackageName), `ApplicationDisplayVersion` (mapped to VersionName), `ApplicationVersion` (mapped to VersionCode), `UseMaui` (identifies MAUI projects), `AndroidPackageFormat`, and `AssemblyName`. + - Runs `dotnet publish "{csprojPath}" -c Release -o "{publishDir}"`. + - After build, searches `bin/Release/{tfm}/publish/` for `.apk` or `.aab` files, auto-locating the build artifact. + - Project type display: MAUI (`true`) or Avalonia (no UseMaui). + +6. **Upload**: Sends the file and form fields via HTTP multipart/form-data. The form fields and their data sources are: + + | Field | Source | Example | + |-------|--------|---------| + | `Name` | ProductName (user input) | `MyApp` | + | `Version` | VersionName (auto-parsed) | `2.0.0` | + | `Hash` | SHA256 (auto-computed) | `a1b2c3d4...` | + | `Format` | Package format (auto-detected) | `.apk` / `.aab` | + | `Size` | File size (auto-computed) | `50000000` | + | `AppType` | Fixed value `"1"` | `1` | + | `Platform` | Platform field (default 4=Android) | `4` | + | `ProductId` | ProductId (user-entered GUID) | `2d974e2a-...` | + | `IsForcibly` | Force update toggle | `true` / `false` | + + The upload service supports the following configuration: + - **Server URL**: Server base address + - **Upload Endpoint**: API path, defaults to `/Packet/Create` + - **Timeout**: Timeout in seconds + - **Retry Count**: Retry attempts on failure (exponential backoff) + - **Auth**: Authentication configuration, supports Basic / Bearer Token / API Key modes (credentials stored encrypted via DPAPI) + +7. **Version record export**: After a successful upload, generates `mobile_version_{timestamp}.json` with full version metadata. You can also use **Export Record Only** to generate the record without uploading — the URL field will be `"manual"`. ### Output @@ -447,6 +483,11 @@ Use the Mobile module for Android app releases: | Simulation port conflict | Change `ServerPort` or free up local port 5000 | | Hash mismatch after client download | Re-compute hash on the file that was actually uploaded to CDN/OSS; check for proxy re-compression | | Upgrade process doesn't start | Verify `updateAppName` and `updatePath` in `generalupdate.manifest.json` match the publish directory structure | +| Mobile analysis shows "Metadata extraction warning" | AXML parser could not find the expected attributes. Common causes: the APK uses resource ID references instead of direct string values; or the APK has been packed/obfuscated and the AndroidManifest.xml structure was modified. You can fill in PackageName, VersionName, and VersionCode manually | +| Mobile Project Mode Build & Locate fails | Verify that the .NET SDK is installed and supports the target framework. Ensure the `.csproj` contains an `-android` target framework. Make sure the output directory `bin/Release/{tfm}/publish/` is not write-protected | +| Mobile Project Mode "Build output not found" | `dotnet publish` succeeded but no `.apk`/`.aab` was found in the expected directory. Check the `AndroidPackageFormat` setting in `.csproj` (default `aab;apk` produces APK first), and verify that the TFM was resolved correctly | +| Mobile upload fails | Check that the server URL and endpoint path are configured correctly. Verify the server authentication method (Basic / Bearer / API Key) matches the tool configuration. Review the tool logs for the HTTP status code and error message | +| Mobile client update fails after upload | Confirm that the version record JSON returned by the server has `Platform` set to `4` (Android), and the `Format` field matches the APK/AAB format the client expects | --- diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md index 2ba7d5d..d7340d0 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/quickstart/GeneralUpdate.PacketTool.md @@ -30,9 +30,9 @@ dotnet run --project GeneralUpdate.Tools.csproj 前往 [GeneralUpdate.Tools Releases](https://github.com/GeneralLibrary/GeneralUpdate.Tools/releases) 下载对应平台的可执行文件,直接运行即可。 -> Simulation 模块内部会调用 `dotnet publish` 构建测试应用,因此使用仿真功能时必须安装 .NET SDK,仅运行 Patch / Extension / OSS / Config 模块则不需要。 +> Simulation 模块内部会调用 `dotnet publish` 构建测试应用,因此使用仿真功能时必须安装 .NET SDK。Mobile 模块的项目模式(Build & Locate)也会调用 `dotnet publish`,同样需要 .NET SDK。仅运行 Patch / Extension / OSS / Config 模块以及 Mobile 的文件模式则不需要。 -## 六个模块速览 +## 七个模块速览 | 模块 | 你提供 | 工具产出 | 下游消费者 | |------|--------|----------|------------| @@ -42,6 +42,7 @@ dotnet run --project GeneralUpdate.Tools.csproj | **Config** | Client/Upgrade 的 `.csproj` | `generalupdate.manifest.json` + `sample_output/` 发布目录 | Client/Upgrade 启动引导 | | **Simulation** | 旧版本目录 + 补丁 ZIP | 本地更新服务 + `simulation_report.md` | 发布前质量把关 | | **Hash** | 本地文件(ZIP) | SHA256 小写十六进制字符串 | 完整性校验、服务端版本记录 | +| **Mobile** | APK/AAB 文件或 MAUI/Avalonia Android 的 `.csproj` | `mobile_version_{timestamp}.json` 版本记录 | 移动端更新服务端、GeneralUpdate.Avalonia/Maui 组件 | --- @@ -320,9 +321,139 @@ Generate Sample 额外输出: --- +## Mobile:移动端打包 + +### 解决什么问题 + +如果你使用 `GeneralUpdate.Avalonia.Android` 或 `GeneralUpdate.Maui.Android` 组件为 Android 应用提供自动更新能力,每次发布新版本时都需要获取 APK/AAB 文件的元数据(包名、版本号、SHA256 哈希、文件大小),并将其上传到服务端进行版本管理。Mobile 模块把"解析 → 打包 → 上传 → 生成版本记录"这四步收敛到一个界面中。 + +支持两种工作模式: + +- **文件模式**:直接选择 APK 或 AAB 文件,自动解析 AndroidManifest.xml 提取元数据 +- **项目模式**:选择 `.csproj` 项目文件,自动执行 `dotnet publish` 构建,然后定位产物并解析 + +### 输入 + +#### 文件模式 + +| 字段 | 必填 | 说明 | +|------|------|------| +| APK/AAB 文件 | ✅ | 选择 `.apk` 或 `.aab` 文件,工具自动识别格式类型 | +| Output Directory | ❌ | 版本记录 JSON 输出目录,为空时输出到桌面 | +| ProductId | ✅ | 产品标识 GUID,用于区分服务端产品线 | +| Platform | ✅ | 目标平台(默认 Android = 4) | +| Product Name | ❌ | 产品名称,写入版本记录 | +| Release Notes | ❌ | 发布说明 | +| Is Forcibly | ❌ | 是否强制更新 | + +#### 项目模式 + +| 字段 | 必填 | 说明 | +|------|------|------| +| `.csproj` 文件 | ✅ | 选择 MAUI 或 Avalonia Android 项目的 `.csproj`,工具自动解析 `ApplicationId`、`ApplicationDisplayVersion`、`ApplicationVersion` | +| Output Directory | ❌ | 同上 | + +### 操作流程 + +1. **选择模式**:切换 File Mode / Project Mode 开关。 + - **文件模式**:点击 **Select File** 选择 `.apk` 或 `.aab` 文件。 + - **项目模式**:点击 **Select Project** 选择 `.csproj` 文件,然后点击 **Build & Locate** 自动执行 `dotnet publish` 并定位产物。 +2. **Analyze**:点击 Analyze 按钮,工具自动: + - 识别文件格式(APK / Android App Bundle) + - 从 AndroidManifest.xml 中提取 `PackageName`、`VersionName`、`VersionCode` + - 计算 SHA256 哈希和文件大小 +3. **填写上传配置**:确认或编辑自动提取的元数据,填写 ProductId、Product Name 等发布信息。 +4. **Upload**:点击 Upload 上传到服务端,并自动生成版本记录 JSON 文件。 + +### 工具内部做了什么 + +1. **格式检测**:通过文件扩展名(`.apk` / `.aab`)和 ZIP 内部结构(`AndroidManifest.xml` 位置)自动识别包格式。 + - APK 检测:打开 ZIP 文件,检查根目录是否存在 `AndroidManifest.xml`。 + - AAB 检测:打开 ZIP 文件,检查是否存在 `base/manifest/AndroidManifest.xml`。 + - 格式未知时(不是 .apk 也不是 .aab)会直接返回 Unknown。 + +2. **元数据解析**:使用 `AxmlParser` 解析二进制的 AXML(Android Binary XML)格式,从 ZIP 中读取 `AndroidManifest.xml`。解析流程如下: + - **字符串池提取**:读取 AXML 文件的 Chunk 头,找到类型为 `0x0001` 的 StringPool Chunk,从中解析出所有 UTF-16LE 编码的字符串数组。 + - **属性值提取**:遍历 XML 的 Start Element Chunk(类型 `0x0102`),解析属性块(每个属性 20 字节),通过属性名在字符串池中的索引匹配 `package` 和 `versionName`,再通过 `rawValueIndex` 从字符串池中取出属性值。 + - **versionCode 提取**:versionCode 存储为整型属性(类型 `0x10` = INT_DEC 或 `0x11` = INT_HEX),直接从属性的 `typedValueData` 字段(偏移 +16,4 字节)读取有符号整数。 + - AXML 结构与参考:https://justanapplication.wordpress.com/category/android/android-binary-xml/ + +3. **SHA256 计算**:对完整文件计算 SHA256 哈希值,输出小写十六进制字符串。 + +4. **文件大小**:读取文件长度并格式化为人类可读的显示(B / KB / MB / GB)。 + +5. **项目构建**(仅项目模式):选择 `.csproj` 后会触发: + - `MobileCsprojParser.Parse()` 解析 `.csproj` 的 XML,提取 `TargetFramework`(支持单 TFM 和多 TFM,多 TFM 时自动选取包含 `-android` 的目标框架)、`ApplicationId`(映射为 PackageName)、`ApplicationDisplayVersion`(映射为 VersionName)、`ApplicationVersion`(映射为 VersionCode)、`UseMaui`(用于识别 MAUI 项目)、`AndroidPackageFormat`、`AssemblyName`。 + - 调用 `dotnet publish "{csprojPath}" -c Release -o "{publishDir}"`。 + - 构建完成后在 `bin/Release/{tfm}/publish/` 目录搜索 `.apk` 或 `.aab` 文件,自动定位构建产物。 + - 项目类型显示:MAUI(`true`)或 Avalonia(没有 UseMaui)。 + +6. **上传**:通过 HTTP multipart/form-data 将文件上传到服务端。上传表单字段和对应的数据源如下: + + | 字段 | 值来源 | 示例 | + |------|--------|------| + | `Name` | ProductName(用户填写) | `MyApp` | + | `Version` | VersionName(自动解析) | `2.0.0` | + | `Hash` | SHA256(自动计算) | `a1b2c3d4...` | + | `Format` | 包格式(自动识别) | `.apk` / `.aab` | + | `Size` | 文件大小(自动计算) | `50000000` | + | `AppType` | 固定值 `"1"` | `1` | + | `Platform` | Platform(默认 4=Android) | `4` | + | `ProductId` | ProductId(用户填写 GUID) | `2d974e2a-...` | + | `IsForcibly` | 强制更新开关 | `true` / `false` | + + 上传服务支持以下配置: + - **Server URL**:服务端地址 + - **Upload Endpoint**:API 路径,默认 `/Packet/Create` + - **Timeout**:超时时间(秒) + - **Retry Count**:失败重试次数(指数退避) + - **Auth**:认证配置,支持 Basic / Bearer Token / API Key 三种模式(凭据通过 DPAPI 加密存储) + +7. **版本记录导出**:上传成功后自动生成 `mobile_version_{timestamp}.json`,包含完整的版本元数据。也可以在不上传的情况下单独点击 **Export Record Only** 导出记录,此时 URL 字段为 `"manual"`。 + +### 输出 + +``` +{OutputDirectory}/mobile_version_20260614120000.json +``` + +```json +{ + "name": "MyApp", + "version": "2.0.0", + "hash": "a1b2c3d4e5f6...", + "url": "https://server.example.com/packages/app-v2.0.0.apk", + "packageName": "com.example.myapp", + "fileSize": 50000000, + "format": "apk", + "platform": 4, + "productId": "2d974e2a-31e6-4887-9bb1-b4689e98c77a", + "isForcibly": false, + "releaseDate": "2026-06-14T12:00:00.0000000Z" +} +``` + +### 下游如何使用 + +- 将生成的版本记录 JSON 导入或上传到你的更新服务端(如 GeneralSpacestation) +- 客户端(`GeneralUpdate.Avalonia.Android` 或 `GeneralUpdate.Maui.Android`)从服务端查询版本信息时,返回的数据结构与版本记录的内容对应 +- 客户端下载 APK 后使用 `hash` 字段做 SHA256 完整性校验 + +### 支持的 AndroidManifest 字段提取 + +| 清单属性 | 字段名 | 说明 | +|---------|--------|------| +| `package` | `PackageName` | 应用包名(唯一标识) | +| `android:versionName` | `VersionName` | 展示版本号(如 `2.0.0`) | +| `android:versionCode` | `VersionCode` | 内部版本代码(整数) | + +--- + ## 推荐发布工作流 -这个顺序把六个模块串联成一个完整的发布流水线: +### 桌面端更新 + +这个顺序把 Patch、OSS、Config、Simulation 四个模块串联成一个完整的桌面应用发布流水线: ``` ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ @@ -338,6 +469,21 @@ Generate Sample 额外输出: 5. **Simulation**:选择旧版本目录和补丁 ZIP,确认 PASS。 6. **发布上线**:上传补丁 ZIP、OSS 清单到生产环境。 +### 移动端更新 + +使用 Mobile 模块串联移动端 Android 应用发布: + +``` +┌────────────┐ ┌──────────┐ ┌──────────┐ +│ 构建 APK/ │ -> │ Mobile │ -> │ 发布上线 │ +│ AAB 产物 │ │ 解析+上传 │ │ 更新服务 │ +└────────────┘ └──────────┘ └──────────┘ +``` + +1. **构建产物**:在 CI 或本地构建出 `.apk` / `.aab` 文件。 +2. **Mobile**:选择文件或项目,自动解析元数据、计算 SHA256、上传服务端、导出版本记录。 +3. **发布上线**:确认上传成功,客户端通过 `GeneralUpdate.Avalonia.Android` 或 `GeneralUpdate.Maui.Android` 检查更新。 + --- ## 常见问题 @@ -351,6 +497,11 @@ Generate Sample 额外输出: | Simulation 端口冲突 | 修改 `ServerPort` 或释放本地 5000 端口 | | 客户端下载后 Hash 校验失败 | 对**最终上传到 CDN/OSS 的文件**重新计算 Hash,检查是否被中间代理重压缩 | | Upgrade 进程没有启动 | 检查 `generalupdate.manifest.json` 中 `updateAppName` 和 `updatePath` 是否与发布目录结构一致 | +| Mobile 分析时提示 "Metadata extraction warning" | AXML 解析未找到预期属性,常见的两种原因:APK 使用资源 ID 引用而非直接文本存储属性值;或 APK 被加固/混淆后 AndroidManifest.xml 结构被修改。可以手动填写 PackageName、VersionName、VersionCode | +| Mobile 项目模式 Build & Locate 失败 | 确认已安装 .NET SDK 且版本支持目标框架(TFM),检查 `.csproj` 包含 `-android` 目标框架,输出目录 `bin/Release/{tfm}/publish/` 没有被写入保护 | +| Mobile 项目模式 "Build output not found" | `dotnet publish` 成功执行但未在预期目录找到 `.apk`/`.aab`。检查 `.csproj` 中 `AndroidPackageFormat` 设置是否正确(默认 `aab;apk` 优先产生 APK),以及 TFM 是否自动解析正确 | +| Mobile 上传失败 | 检查服务端地址和 Endpoint 配置是否正确,确认服务端认证方式(Basic / Bearer / API Key)与工具配置一致,查看工具日志中的 HTTP 状态码和错误消息 | +| Mobile 上传后客户端更新失败 | 确认服务端返回的版本记录 JSON 中 `Platform` 字段为 `4`(Android),`Format` 字段与客户端期望的 APK/AAB 格式一致 | --- @@ -359,4 +510,6 @@ Generate Sample 额外输出: - [GeneralUpdate.Core](../doc/GeneralUpdate.Core):Client/Upgrade 更新主流程 - [GeneralUpdate.Differential](../doc/GeneralUpdate.Differential):差分算法 Clean/Dirty 模式 - [GeneralUpdate.Extension](../doc/GeneralUpdate.Extension):扩展包安装与版本管理 +- [GeneralUpdate.Avalonia.Android](../doc/GeneralUpdate.Avalonia.Android):Avalonia Android APK 更新组件 +- [GeneralUpdate.Maui.Android](../doc/GeneralUpdate.Maui.Android):MAUI Android APK 更新组件 - [入门实战手册](./Beginner%20cookbook):从零跑通完整更新闭环 From e2abe7962a44a58a4d00829f3e5f8359cab8d35e Mon Sep 17 00:00:00 2001 From: JusterZhu Date: Sun, 14 Jun 2026 12:13:08 +0800 Subject: [PATCH 2/3] docs: rename 'Quickstart' to 'Cookbook' for Avalonia/Maui Android guides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Avalonia Android: 快速入门 → 实战手册, Quickstart → Cookbook - MAUI Android: 快速入门 → 实战手册, Quickstart → Cookbook Aligns naming convention with Beginner cookbook. Co-Authored-By: Claude --- website/docs/quickstart/Avalonia Android cookbook.md | 4 ++-- website/docs/quickstart/Maui Android cookbook.md | 4 ++-- .../current/quickstart/Avalonia Android cookbook.md | 4 ++-- .../current/quickstart/Maui Android cookbook.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/website/docs/quickstart/Avalonia Android cookbook.md b/website/docs/quickstart/Avalonia Android cookbook.md index 08a19db..8d65d6d 100644 --- a/website/docs/quickstart/Avalonia Android cookbook.md +++ b/website/docs/quickstart/Avalonia Android cookbook.md @@ -1,9 +1,9 @@ --- sidebar_position: 4 -title: Avalonia Android 更新入门 +title: Avalonia Android 实战手册 --- -# GeneralUpdate.Avalonia.Android 快速入门 +# GeneralUpdate.Avalonia.Android 实战手册 这篇手册面向需要在 Avalonia 应用中集成 Android APK 自动更新的开发者。目标是用最少的代码跑通"检查更新 → 下载 APK → 校验 SHA256 → 启动安装器"的完整流程。 diff --git a/website/docs/quickstart/Maui Android cookbook.md b/website/docs/quickstart/Maui Android cookbook.md index e2d53bd..0de6f39 100644 --- a/website/docs/quickstart/Maui Android cookbook.md +++ b/website/docs/quickstart/Maui Android cookbook.md @@ -1,9 +1,9 @@ --- sidebar_position: 5 -title: MAUI Android 更新入门 +title: MAUI Android 实战手册 --- -# GeneralUpdate.Maui.Android 快速入门 +# GeneralUpdate.Maui.Android 实战手册 这篇手册面向需要在 MAUI 应用中集成 Android APK 自动更新的开发者。目标是用最少的代码跑通"检查更新 → 下载 APK → 校验 SHA256 → 启动安装器"的完整流程。 diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Avalonia Android cookbook.md b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Avalonia Android cookbook.md index 11497fd..f013d61 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Avalonia Android cookbook.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Avalonia Android cookbook.md @@ -1,9 +1,9 @@ --- sidebar_position: 4 -title: Avalonia Android Update Quickstart +title: Avalonia Android Cookbook --- -# GeneralUpdate.Avalonia.Android Quickstart +# GeneralUpdate.Avalonia.Android Cookbook This guide is for developers who need to integrate Android APK auto-update into their Avalonia applications. The goal is to complete the "check update → download APK → verify SHA256 → launch installer" workflow with minimal code. diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Maui Android cookbook.md b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Maui Android cookbook.md index ffb1393..c1cebcd 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Maui Android cookbook.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/quickstart/Maui Android cookbook.md @@ -1,9 +1,9 @@ --- sidebar_position: 5 -title: MAUI Android Update Quickstart +title: MAUI Android Cookbook --- -# GeneralUpdate.Maui.Android Quickstart +# GeneralUpdate.Maui.Android Cookbook This guide is for developers who need to integrate Android APK auto-update into their .NET MAUI applications. The goal is to complete the "check update → download APK → verify SHA256 → launch installer" workflow with minimal code. From 9b0d31c6124266fccb9bb63aa214512776b06cd7 Mon Sep 17 00:00:00 2001 From: JusterZhu Date: Sun, 14 Jun 2026 13:00:52 +0800 Subject: [PATCH 3/3] docs: add Bilibili demo videos to cookbook pages - GeneralUpdate.Tools Mobile: Android packaging demo (BV1ctJF6XEJs) - Avalonia Android cookbook: upgrade demo (BV1HtJF6XET3) - MAUI Android cookbook: upgrade demo (BV1ntJF6XEvG) Co-Authored-By: Claude --- website/docs/quickstart/Avalonia Android cookbook.md | 9 +++++++++ website/docs/quickstart/GeneralUpdate.PacketTool.md | 9 +++++++++ website/docs/quickstart/Maui Android cookbook.md | 9 +++++++++ .../current/quickstart/Avalonia Android cookbook.md | 9 +++++++++ .../current/quickstart/GeneralUpdate.PacketTool.md | 9 +++++++++ .../current/quickstart/Maui Android cookbook.md | 9 +++++++++ 6 files changed, 54 insertions(+) diff --git a/website/docs/quickstart/Avalonia Android cookbook.md b/website/docs/quickstart/Avalonia Android cookbook.md index 8d65d6d..f4a16c4 100644 --- a/website/docs/quickstart/Avalonia Android cookbook.md +++ b/website/docs/quickstart/Avalonia Android cookbook.md @@ -7,6 +7,15 @@ title: Avalonia Android 实战手册 这篇手册面向需要在 Avalonia 应用中集成 Android APK 自动更新的开发者。目标是用最少的代码跑通"检查更新 → 下载 APK → 校验 SHA256 → 启动安装器"的完整流程。 +