diff --git a/website/docs/quickstart/Avalonia Android cookbook.md b/website/docs/quickstart/Avalonia Android cookbook.md
index 08a19db..f4a16c4 100644
--- a/website/docs/quickstart/Avalonia Android cookbook.md
+++ b/website/docs/quickstart/Avalonia Android cookbook.md
@@ -1,12 +1,21 @@
---
sidebar_position: 4
-title: Avalonia Android 更新入门
+title: Avalonia Android 实战手册
---
-# GeneralUpdate.Avalonia.Android 快速入门
+# GeneralUpdate.Avalonia.Android 实战手册
这篇手册面向需要在 Avalonia 应用中集成 Android APK 自动更新的开发者。目标是用最少的代码跑通"检查更新 → 下载 APK → 校验 SHA256 → 启动安装器"的完整流程。
+
+
:::info 前置知识
这篇手册假设你已经有一个 Avalonia 项目并配置好了 Android 目标框架。如果你还没有 Avalonia Android 项目,请先参考 [Avalonia 官方文档](https://docs.avaloniaui.net/) 创建。
:::
diff --git a/website/docs/quickstart/GeneralUpdate.PacketTool.md b/website/docs/quickstart/GeneralUpdate.PacketTool.md
index 37e8511..92b10a6 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 的文件模式则不需要。
## 七个模块速览
@@ -332,6 +332,15 @@ Generate Sample 额外输出:
如果你使用 `GeneralUpdate.Avalonia.Android` 或 `GeneralUpdate.Maui.Android` 组件为 Android 应用提供自动更新能力,每次发布新版本时都需要获取 APK/AAB 文件的元数据(包名、版本号、SHA256 哈希、文件大小),并将其上传到服务端进行版本管理。Mobile 模块把"解析 → 打包 → 上传 → 生成版本记录"这四步收敛到一个界面中。
+
+
支持两种工作模式:
- **文件模式**:直接选择 APK 或 AAB 文件,自动解析 AndroidManifest.xml 提取元数据
@@ -373,12 +382,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 +511,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/docs/quickstart/Maui Android cookbook.md b/website/docs/quickstart/Maui Android cookbook.md
index e2d53bd..e93c00f 100644
--- a/website/docs/quickstart/Maui Android cookbook.md
+++ b/website/docs/quickstart/Maui Android cookbook.md
@@ -1,12 +1,21 @@
---
sidebar_position: 5
-title: MAUI Android 更新入门
+title: MAUI Android 实战手册
---
-# GeneralUpdate.Maui.Android 快速入门
+# GeneralUpdate.Maui.Android 实战手册
这篇手册面向需要在 MAUI 应用中集成 Android APK 自动更新的开发者。目标是用最少的代码跑通"检查更新 → 下载 APK → 校验 SHA256 → 启动安装器"的完整流程。
+
+
:::info 前置知识
这篇手册假设你已经有一个 .NET MAUI 项目并配置好了 Android 目标框架。如果你还没有 MAUI Android 项目,请先参考 [.NET MAUI 官方文档](https://learn.microsoft.com/dotnet/maui/) 创建。
:::
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..b1b8b9c 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,12 +1,21 @@
---
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.
+
+
:::info Prerequisites
This guide assumes you already have an Avalonia project configured for Android target framework. If not, please refer to the [Avalonia documentation](https://docs.avaloniaui.net/) first.
:::
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..e2b494c 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
@@ -312,6 +312,15 @@ In the **OSS Config** module, click **ComputeHash**, select a local ZIP file, an
If you use `GeneralUpdate.Avalonia.Android` or `GeneralUpdate.Maui.Android` to provide auto-update for your Android apps, each release requires extracting APK/AAB metadata (package name, version, SHA256 hash, file size) and uploading it to the server for version management. The Mobile module consolidates "parse → package → upload → generate version record" into a single interface.
+
+
Supports two modes:
- **File mode**: Select an APK or AAB file directly; the tool automatically parses AndroidManifest.xml to extract metadata.
@@ -353,12 +362,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 +492,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/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..44d9204 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,12 +1,21 @@
---
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.
+
+
:::info Prerequisites
This guide assumes you already have a .NET MAUI project configured for Android target framework. If not, please refer to the [.NET MAUI documentation](https://learn.microsoft.com/dotnet/maui/) first.
:::
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):从零跑通完整更新闭环