mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 17:10:43 +00:00
按用户定的版本规矩,这一轮既有新内容又有重构,所以升第二位: 1.9.0 -> 2.0.0(最后一位清 0)。 == 一、安装时就能设中转服务器(用户要求)== 安装向导那一页现在是两个输入框:配对码 + 中转服务器。 装的时候是"第一次设置",最该一次把地址填好,不然装完还得去 双击 exe 找设置窗口,很容易漏。 只填域名就行(自动补 https://),留空 = 只走局域网。 批量静默部署同样支持: ykxmz-setup-2.0.0.exe /VERYSILENT /CODE=246810 /RELAY=relay.你的域名 为此新增了一个 --relay-url 参数: --relay 连接一次、打印状态、然后退出(人工排查用) --relay-url 只写进配置,不连接、不退出(安装流程用) 用错那个的话,安装包的命令链会在中间就 return,后面的 --silent 根本跑不到 —— 所以必须分开。 == 二、手表端新增「设置」页(用户要求)== 用户原话:"安卓端加一个设置,各种设置就在这里面调"。 以前设置散在首页(只有一个"中转设置"按钮),现在统一收进设置页: * 中转服务器(填写 / 一键清空) * 记住的配对码(显示 / 清除) * 已配对的电脑(看数量 / 清空,带二次确认) * 关于(版本号从 APK 读,不会和代码对不上) == 三、中转地址默认留空 + 一次性迁移(用户报的问题)== 用户原话:"安卓端为什么还是默认填的我的中转站,以后改成手动填"。 代码里的默认值早就是空的了,但用户看到的还是那个地址 —— 因为**老版本 1.5.0 把作者的域名硬编码成了默认值**,第一次运行就 存进了 SharedPreferences。装新 APK 不会清偏好,所以那个值一直留着。 用户其实从来没"选"过这个地址,是程序硬塞的。 所以加了 migrateLegacyRelay():存的值如果正好等于当时内置的域名, 就当成没设过、清掉。只清完全相等的,用户手填的不会动。 == 四、两个测试自身的毛病 == * test_lan_optimize 那条"没有把旧公网域名当默认值"太粗 —— 它查的是源码里任何位置,于是迁移注释里引用那行老代码就把它判红了。 改成先剥掉注释再查(断言要测的是"有没有把它当默认值")。 * test_image_modes 偶发红:它开真实 Tk 全屏窗口,在全量套件里跑 偶尔起不来(单独跑 19/19 全过)。加了有界重试。 偶发红的测试会让"全量通过"失去意义。 == 五、新增防复发断言 == _tests/test_relay_default_blank.py(15 项,回归阶段 3a3b): * 默认值必须是空串 * 除了迁移清单,源码里不许有写死的中转域名 * 迁移必须真的被调用(不是只定义) * 迁移必须是 remove,不能换成另一个硬编码值 * Windows 端的默认也得是空 理由:用户说过"这个中转站我就自己用,不对外" —— 值得用断言钉死。 == 六、顺手修的 == * release_all.py 崩在 Gitee 那一步:Gitee 的 GET /releases/tags/{tag} 在"标签存在、但还没发行版"时返回的是 **HTTP 200 + JSON null**(不是 404),于是 .get("id") 直接 AttributeError。发 1.9.0 时踩到,已改成容忍 None。 * installer/build_installer.py 里 license-combined.txt 是从 docs/ 三份文档重新生成的,所以光改生成物没用(下次构建又变回去)。 改成在 build_license() 里统一注入当前版本。 * ExE 文件属性里的版本(version_info.txt)从 1.7.1 起就一直没跟上。 全量回归 43 个阶段全部通过。
134 lines
5.2 KiB
PowerShell
134 lines
5.2 KiB
PowerShell
# 用 aapt2 + javac + d8 + zipalign + apksigner 手工构建 APK(不需要 Gradle)
|
||
# 用法: powershell -File android\build_apk.ps1
|
||
#
|
||
# 注意:刻意不用 $ErrorActionPreference="Stop"。
|
||
# 原生工具的告警(javac 的 deprecation note 等)会写 stderr,
|
||
# 在 Stop 模式下会被 PowerShell 当成致命错误中断构建。
|
||
# 改为每一步显式检查 $LASTEXITCODE。
|
||
$ErrorActionPreference = "Continue"
|
||
|
||
$android = $PSScriptRoot # LanRemote/android(本脚本所在目录)
|
||
$root = Split-Path -Parent $android # LanRemote
|
||
$tc = Join-Path $root "..\starklink\toolchain"
|
||
$jdk = Join-Path $tc "jdk17"
|
||
$sdk = Join-Path $tc "android-sdk"
|
||
$bt = Join-Path $sdk "build-tools\34.0.0"
|
||
$androidJar = Join-Path $sdk "platforms\android-34\android.jar"
|
||
$keystore = Join-Path $tc "debug.keystore"
|
||
|
||
$javac = Join-Path $jdk "bin\javac.exe"
|
||
$keytool = Join-Path $jdk "bin\keytool.exe"
|
||
$jar = Join-Path $jdk "bin\jar.exe"
|
||
|
||
$aapt2 = Join-Path $bt "aapt2.exe"
|
||
$zipalign = Join-Path $bt "zipalign.exe"
|
||
$apksigner= Join-Path $bt "apksigner.bat"
|
||
$d8 = Join-Path $bt "d8.bat"
|
||
|
||
$work = Join-Path $android "build"
|
||
$outDir = Join-Path $root "dist"
|
||
$apkName = "ykxmz-watch-2.0.0.apk"
|
||
|
||
function Step($text) { Write-Host "`n=== $text ===" -ForegroundColor Cyan }
|
||
|
||
# 前置检查
|
||
foreach ($tool in @($javac, $aapt2, $d8, $zipalign, $apksigner)) {
|
||
if (-not (Test-Path $tool)) { throw "缺少工具: $tool" }
|
||
}
|
||
if (-not (Test-Path $androidJar)) { throw "缺少 android.jar: $androidJar" }
|
||
if (-not (Test-Path $keystore)) { throw "缺少签名用 keystore: $keystore" }
|
||
|
||
$env:JAVA_HOME = $jdk
|
||
$env:PATH = "$(Join-Path $jdk 'bin');$env:PATH"
|
||
|
||
if (Test-Path $work) { Remove-Item -Recurse -Force $work }
|
||
New-Item -ItemType Directory -Force -Path $work | Out-Null
|
||
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
||
|
||
# ---------------- 1. 编译资源 ----------------
|
||
Step "1/6 aapt2 compile 资源"
|
||
$compiled = Join-Path $work "res.zip"
|
||
& $aapt2 compile --dir (Join-Path $android "res") -o $compiled
|
||
if ($LASTEXITCODE -ne 0) { throw "aapt2 compile 失败" }
|
||
|
||
# ---------------- 2. 链接资源 + 生成 R.java ----------------
|
||
Step "2/6 aapt2 link 生成资源表与 R.java"
|
||
$genDir = Join-Path $work "gen"
|
||
New-Item -ItemType Directory -Force -Path $genDir | Out-Null
|
||
$unsigned = Join-Path $work "app-unsigned.apk"
|
||
& $aapt2 link `
|
||
-o $unsigned `
|
||
-I $androidJar `
|
||
--manifest (Join-Path $android "AndroidManifest.xml") `
|
||
-R $compiled `
|
||
--java $genDir `
|
||
--min-sdk-version 24 `
|
||
--target-sdk-version 34 `
|
||
--version-code 5 `
|
||
--version-name "2.0.0" `
|
||
--auto-add-overlay
|
||
if ($LASTEXITCODE -ne 0) { throw "aapt2 link 失败" }
|
||
|
||
# ---------------- 3. 编译 Java ----------------
|
||
Step "3/6 javac 编译 Java 源码"
|
||
$classesDir = Join-Path $work "classes"
|
||
New-Item -ItemType Directory -Force -Path $classesDir | Out-Null
|
||
|
||
$javaSources = @()
|
||
$javaSources += Get-ChildItem -Recurse -Filter *.java -Path (Join-Path $android "src") | ForEach-Object { $_.FullName }
|
||
$javaSources += Get-ChildItem -Recurse -Filter R.java -Path $genDir -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName }
|
||
if ($javaSources.Count -eq 0) { throw "没有找到 Java 源文件" }
|
||
Write-Host "源文件 $($javaSources.Count) 个"
|
||
|
||
& $javac -source 8 -target 8 -nowarn -Xlint:none -encoding UTF-8 `
|
||
-bootclasspath $androidJar `
|
||
-d $classesDir `
|
||
$javaSources 2>&1 | Out-String | Write-Host
|
||
if ($LASTEXITCODE -ne 0) { throw "javac 编译失败" }
|
||
|
||
# ---------------- 4. d8 转 dex ----------------
|
||
Step "4/6 d8 转换为 classes.dex"
|
||
$classesJar = Join-Path $work "classes.jar"
|
||
& $jar cf $classesJar -C $classesDir .
|
||
if ($LASTEXITCODE -ne 0) { throw "打包 classes.jar 失败" }
|
||
|
||
$dexDir = Join-Path $work "dex"
|
||
New-Item -ItemType Directory -Force -Path $dexDir | Out-Null
|
||
& $d8 --lib $androidJar --min-api 24 --output $dexDir $classesJar 2>&1 | Out-String | Write-Host
|
||
if ($LASTEXITCODE -ne 0) { throw "d8 失败" }
|
||
$dex = Join-Path $dexDir "classes.dex"
|
||
if (-not (Test-Path $dex)) { throw "未生成 classes.dex" }
|
||
Write-Host ("classes.dex 大小 {0:N1} KB" -f ((Get-Item $dex).Length / 1KB))
|
||
|
||
# ---------------- 5. 组装 APK ----------------
|
||
Step "5/6 组装 APK"
|
||
& python (Join-Path $root "_build\pack_apk.py") $unsigned $dex
|
||
if ($LASTEXITCODE -ne 0) { throw "写入 classes.dex 失败" }
|
||
|
||
$aligned = Join-Path $work "app-aligned.apk"
|
||
& $zipalign -f 4 $unsigned $aligned
|
||
if ($LASTEXITCODE -ne 0) { throw "zipalign 失败" }
|
||
|
||
# ---------------- 6. 签名 ----------------
|
||
Step "6/6 apksigner 签名"
|
||
$final = Join-Path $outDir $apkName
|
||
if (Test-Path $final) { Remove-Item $final -Force }
|
||
& $apksigner sign `
|
||
--ks $keystore `
|
||
--ks-pass pass:android `
|
||
--key-pass pass:android `
|
||
--ks-key-alias androiddebugkey `
|
||
--v1-signing-enabled true `
|
||
--v2-signing-enabled true `
|
||
--out $final `
|
||
$aligned
|
||
if ($LASTEXITCODE -ne 0) { throw "签名失败" }
|
||
|
||
Step "验证签名"
|
||
& $apksigner verify --print-certs $final
|
||
if ($LASTEXITCODE -ne 0) { throw "签名校验失败" }
|
||
|
||
Step "构建完成"
|
||
Write-Host ("APK: {0}" -f $final) -ForegroundColor Green
|
||
Write-Host ("大小: {0:N2} MB" -f ((Get-Item $final).Length / 1MB)) -ForegroundColor Green
|