Files
opendance-android/build/check-apk-version.sh
T
zijunchiang 31b6ddd0fa test(packaging): APK 产物版本元数据校验(T-AND-013)+ 修 die 在定义前被调用
文档 §11.2 要求「版本号单一来源 + 可核对」。本仓库原有校验只覆盖**构建配置**
(gradle verifyReleaseVersion 比 versionName ↔ project.yaml)。但版本号真正被
系统与用户看到的地方是 **APK 的 AndroidManifest**:安装界面、应用信息页、
dumpsys package 读的都是它。构建缓存、复用旧 APK、打包时拷错文件都会造成
「配置全对、产物是旧版」——配置层校验抓不到。

这不是假设:同批工作里 Windows 端 v0.2.1 的发布包就是配置文件全一致、
exe 属性页显示 0.1.0(opendance-windows/tasks/017-pe-version.md)。

新增:
  * build/check_apk_version.py:直接解析 APK 内 AndroidManifest.xml(二进制 AXML)
    的 versionName / versionCode。只依赖 Python 标准库,不需要 Android SDK/aapt2。
    AXML 解析:顶层 ResChunk_header → 字符串池(UTF-8 与 UTF-16 都要处理)→
    START_ELEMENT;属性名本身就在字符串池里,按文本匹配即可,无需资源映射表;
  * build/check-apk-version.sh:薄包装,期望版本缺省取 project.yaml,
    并校验 versionCode == 10000*主 + 100*次 + 修订(§11.1);
  * build/verify.sh 步骤 3/3 新增「版本元数据」计分项(原先只 aapt2 打印一行);
  * build/package-release.sh 打包前校验源 APK,不一致即 die。

交叉验证(与 aapt2 dump badging 逐项一致):
  v0.1.0 APK -> versionCode 1 / versionName 0.1.0
  v0.2.0 APK -> versionCode 200 / versionName 0.2.0
  app/build/outputs/apk/release/app-release.apk -> 同 v0.2.0
反向验证(用真实旧产物当负例):
  bash build/check-apk-version.sh dist-release/opendance-android-v0.1.0/app-release.apk
    ✗ versionName 是 '0.1.0',期望 '0.2.0'
    ✗ versionCode 是 1,期望 200
    退出码 1

顺带修复:build/package-release.sh 第 31/33 行用 die 报版本不一致,但 die()
到第 40 行才定义。命中该分支时输出的是
    build/package-release.sh: 行 31: die: 未找到命令   (退出码 127)
脚本确实中止了,但用户完全看不出真实原因。现把 log()/die() 移到首次使用之前:
    [error] 版本号不一致:参数/versionName=9.9.9,project.yaml=0.2.0  (退出码 1)

未新发版本:APK 内容与 v0.2.0 完全一致(产物侧校验证明其 versionName/versionCode
本就正确),本次改动只涉及构建/校验脚本与文档,故不为它提版本号;
README.txt 的新增自检项会随下一次 Android 发布进入发布包。
2026-09-17 04:29:52 +08:00

56 lines
2.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ============================================================
# OpenDance Studio —— APK 版本元数据校验(读产物本身)
#
# 文档 §11.2 要求「版本号单一来源 + 可核对」。`app/build.gradle.kts` 里的
# `verifyReleaseVersion` 任务只比**构建配置**(versionName ↔ project.yaml);
# 而版本号真正被系统与用户看到的地方是 **APK 的 AndroidManifest** ——
# 安装界面、应用信息页、`dumpsys package` 读的都是它。
# 构建缓存、复用旧 APK、打包时拷错文件都会让「配置全对、产物是旧版」;
# Windows 端 v0.2.1 就踩过同类的坑(配置文件全一致,exe 属性页显示 0.1.0,
# 见 opendance-windows/tasks/017-pe-version.md)。
#
# 本脚本直接读产物,因此与构建配置无关也能发现漂移。
#
# 用法:
# bash build/check-apk-version.sh <apk> [期望版本 X.Y.Z]
# 期望版本缺省时取 project.yaml 的 version;此时同时校验
# versionCode == 10000*主 + 100*次 + 修订(文档 §11.1)。
# ============================================================
set -uo pipefail
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cd "$PROJECT_DIR"
APK="${1:-}"
EXPECTED="${2:-$(sed -n 's/^version:[[:space:]]*//p' project.yaml | head -1)}"
if [ -z "$APK" ]; then
echo "用法:bash build/check-apk-version.sh <apk> [期望版本 X.Y.Z]" >&2
exit 2
fi
if [ ! -f "$APK" ]; then
echo "✗ 找不到文件:$APK" >&2
exit 2
fi
# 解析器只用 Python 标准库读二进制 AXML(不依赖 Android SDK / aapt2)。
# 已用 aapt2 dump badging 在 v0.1.0 与 v0.2.0 两个真实 APK 上交叉验证一致。
PYTHON="${PYTHON_BIN:-}"
if [ -z "$PYTHON" ]; then
for candidate in python3 python; do
if command -v "$candidate" >/dev/null 2>&1; then PYTHON="$candidate"; break; fi
done
fi
if [ -z "$PYTHON" ]; then
echo "✗ 未找到 python3(用于解析 APK 内的二进制 AndroidManifest.xml)" >&2
echo " Debian/Ubuntu: apt-get install -y python3" >&2
exit 2
fi
if [ -n "$EXPECTED" ]; then
"$PYTHON" "$PROJECT_DIR/build/check_apk_version.py" "$APK" --expect-version "$EXPECTED"
else
"$PYTHON" "$PROJECT_DIR/build/check_apk_version.py" "$APK"
fi