drukscode-v2/docs/zh/developer/export-pipeline.md
OpenCode AI e9899d2e6d
Some checks failed
Android CI Build / check (push) Has been cancelled
Android CI Build / package-apks (push) Has been cancelled
Docs Deploy / build (push) Has been cancelled
Module Market Check / Validate modules/ (push) Has been cancelled
Module Market Publish / Generate submissions.json (push) Has been cancelled
Docs Deploy / deploy (push) Has been cancelled
Initial DruksCode V2: fresh fork of web-to-app (f3b488e) with DruksCode identity
- Package rename com.webtoapp -> br.com.drukstech.codeapp
- Product rename WebToApp/web-to-app -> DruksCode/drukscode
- Design system Wta* -> Dkc*
- applicationId br.com.drukstech.codeapp (.play for gplay flavor)
- rootProject.name DruksCode
- Fresh git history (upstream kept as remote for sync)
2026-09-12 02:42:02 +02:00

67 lines
3.3 KiB
Markdown

# 导出管线
导出管线把 `WebApp` 模型变成已签名的 APK。它位于 `app/src/main/java/br/com/drukstech/codeapp/core/apkbuilder/`(约 24 个文件)。
## 关键类
| 文件 | 角色 |
| --- | --- |
| `ApkBuilder.kt` | 编排 APK 组装 + 签名。包含 `WebApp.toApkConfig(...)`。 |
| `ApkConfig.kt` | 主配置 schema:`data class ApkConfig(meta, activation, adBlock, webView, proxy, dns, nodejs, phpApp, pythonApp, goApp, multiWeb, ...)`。导出 APK 能编码的一切。 |
| `ApkConfigJsonFactory.kt` | 把 `ApkConfig` 序列化为 shell 读取的 assets JSON;含 `ApkConfigValidator`。 |
| `ApkTemplate.kt` / `ShellTemplateProvider.kt` | 定位并加载 shell 模板 APK。 |
| `ApkBuildCache.kt` | 增量重建;定义 `enum class IncrementalBuildMode`(`ModifyApkMode` 只覆盖 `FULL`/`CONTENT_OVERLAY`)。 |
| `AxmlEditor` / `AxmlRebuilder` | 编辑/重建二进制 AndroidManifest(AXML)。 |
| `ArscEditor` / `ArscRebuilder` | 编辑/重建二进制资源表(resources.arsc)。 |
| `JarSigner.kt` | 直接用 `com.android.apksig` 库为 APK 签名(`ApkSigner`,V1/V2/V3 开关)。 |
| `ZipAligner` / `ZipUtils` | zip 对齐与底层 zip 操作。 |
| `ElfAligner16k.kt` | 为原生 `.so` 文件做 16KB 页 ELF 对齐。 |
| `RuntimeAssetEmbedder.kt` | 把运行时资源(Node/PHP/Python/Go)注入 APK。 |
| `NetworkSecurityConfigBuilder.kt` | 生成网络安全配置 XML。 |
相关:`core/playstore/aab/` 负责 AAB/Play 打包;`core/crypto/`(`AssetEncryptor`、`EncryptedApkBuilder`、`KeyManager`)负责资源加密。
## 流程
```text
WebApp(编辑器模型)
→ WebApp.toApkConfig() [ApkBuilder.kt]
→ ApkConfig [类型化 schema,*Block 子对象]
→ ApkConfigJsonFactory [序列化为 app_config.json]
→ 嵌入模板 assets
→ 修改 AXML / ARSC(身份、权限、图标)
→ 嵌入运行时资源(如果是服务端运行时)
→ 签名(V1/V2/V3)
→ 输出 APK
```
## `ApkConfig` 结构
`ApkConfig` 由一个 `MetaBlock` 加数十个功能块组成(`WebViewBlock`、`ProxyBlock`、`DnsBlock`、`NodejsBlock`、`PhpAppBlock`、`PythonAppBlock`、`GoAppBlock`、`MultiWebBlock`、`AdBlockBlock`……)。`ApkConfig` 上的便捷 getter 把它们扁平化(`appName`、`targetUrl`、`adBlockEnabled`……)。
`ApkConfigJsonFactory` 产生的 JSON 字段名**必须匹配** shell 配置类中的 `@SerializedName` 注解 —— 见[配置字段漂移](/zh/developer/config-drift)。
## 增量重建(`ApkBuildCache`)
三种模式(`enum class IncrementalBuildMode`):
| 模式 | 含义 |
| --- | --- |
| `FULL` | 从模板重建。加密构建恒用此模式。 |
| `CONTENT_OVERLAY` | 仅应用内容变化;叠加到先前构建之上。 |
| `REUSE_UNSIGNED` | 对先前构建的未签名 APK 重新签名。 |
规则:
- 缓存键是**内容稳定哈希** —— 绝不用 mtime。
- 模板 / 条目身份必须内容稳定。
- 加密构建总是强制全量重建。
- **不要**把已签名或已改名的 APK 当作模板喂回全量 `modifyApk`。
## 原生库嵌入
- **Node.js** 导出必须嵌入 `libnode_bridge.so` + `libnode.so`(经 `ElfAligner16k` 16KB 对齐)+ `libc++_shared.so`。
- **Go** 导出必须嵌入 `libgo_exec_loader.so`。
缺少任何原生库都会在运行时导致 `loadNode` / `loadJniBridge` 失败。