Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,48 @@ jobs:
$version = (& java -version 2>&1 | Out-String)
$version
if ($version -notmatch '25\.0\.4\.1\+1') { throw "需要 Temurin 25.0.4.1+1,实际是:$version" }
- name: Test SDK fallback and failure handling
shell: pwsh
run: |
pwsh -NoProfile -File .\scripts\test_android_sdk_fallback.ps1
if ($LASTEXITCODE -ne 0) { throw 'SDK fallback tests failed' }
- name: Check android.jar and build APKs
shell: pwsh
env:
TZ: CET-1
run: |
$ErrorActionPreference = 'Stop'
$expectedJarHash = 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a'
# repository2-3.xml: platforms;android-36 r2, SHA-1 2c1a80dd4d9f7d0e6dd336ec603d9b5c55a6f576.
# Google publishes SHA-1 only; this SHA-256 was computed after checking it.
$archiveName = 'platform-36_r02.zip'
$expectedArchiveHash = '37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e'
$jar = Join-Path $env:ANDROID_HOME 'platforms\android-36\android.jar'
if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) { throw "找不到 $jar" }
$hash = (Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a') {
throw "android.jar SHA-256 不符:$hash"
$sdkTemp = $null
try {
if (-not (Test-Path -LiteralPath $jar -PathType Leaf) -or
(Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expectedJarHash) {
Write-Host '预装 android.jar 缺失或 SHA-256 不符,下载 Android 36 r2。'
$sdkTemp = Join-Path $env:RUNNER_TEMP ("android-36-r2-" + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $sdkTemp | Out-Null
$archive = Join-Path $sdkTemp $archiveName
Invoke-WebRequest -Uri "https://dl.google.com/android/repository/$archiveName" -OutFile $archive
$hash = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne $expectedArchiveHash) { throw "SDK 压缩包 SHA-256 不符:$hash" }
$sdk = Join-Path $sdkTemp 'sdk'
Expand-Archive -LiteralPath $archive -DestinationPath $sdk
$jar = Join-Path $sdk 'android-36\android.jar'
if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) { throw "找不到 $jar" }
$hash = (Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne $expectedJarHash) { throw "android.jar SHA-256 不符:$hash" }
}
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar
if ($LASTEXITCODE -ne 0) { throw "APK 构建失败(退出码 $LASTEXITCODE)" }
} finally {
if ($sdkTemp -and (Test-Path -LiteralPath $sdkTemp)) {
Remove-Item -LiteralPath $sdkTemp -Recurse -Force
}
}
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar

privacy:
runs-on: ubuntu-24.04
Expand Down
33 changes: 30 additions & 3 deletions .github/workflows/verify-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,37 @@ jobs:
TZ: CET-1
run: |
$ErrorActionPreference = 'Stop'
$expectedJarHash = 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a'
# repository2-3.xml: platforms;android-36 r2, SHA-1 2c1a80dd4d9f7d0e6dd336ec603d9b5c55a6f576.
# Google publishes SHA-1 only; this SHA-256 was computed after checking it.
$archiveName = 'platform-36_r02.zip'
$expectedArchiveHash = '37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e'
$jar = Join-Path $env:ANDROID_HOME 'platforms\android-36\android.jar'
$hash = (Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a') { throw "android.jar SHA-256 不符:$hash" }
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar
$sdkTemp = $null
try {
if (-not (Test-Path -LiteralPath $jar -PathType Leaf) -or
(Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expectedJarHash) {
Write-Host '预装 android.jar 缺失或 SHA-256 不符,下载 Android 36 r2。'
$sdkTemp = Join-Path $env:RUNNER_TEMP ("android-36-r2-" + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $sdkTemp | Out-Null
$archive = Join-Path $sdkTemp $archiveName
Invoke-WebRequest -Uri "https://dl.google.com/android/repository/$archiveName" -OutFile $archive
$hash = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne $expectedArchiveHash) { throw "SDK 压缩包 SHA-256 不符:$hash" }
$sdk = Join-Path $sdkTemp 'sdk'
Expand-Archive -LiteralPath $archive -DestinationPath $sdk
$jar = Join-Path $sdk 'android-36\android.jar'
if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) { throw "找不到 $jar" }
$hash = (Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash.ToLowerInvariant()
if ($hash -ne $expectedJarHash) { throw "android.jar SHA-256 不符:$hash" }
}
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar
if ($LASTEXITCODE -ne 0) { throw "APK 构建失败(退出码 $LASTEXITCODE)" }
} finally {
if ($sdkTemp -and (Test-Path -LiteralPath $sdkTemp)) {
Remove-Item -LiteralPath $sdkTemp -Recurse -Force
}
}
- name: Sign the build with a one-time RSA-4096 key
shell: pwsh
run: |
Expand Down
36 changes: 35 additions & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ You need:
- Windows and PowerShell 7.2 or newer (`pwsh`);
- JDK 17 or newer (the maintainer uses Temurin 25, with `javac --release 17`): set `JAVA_HOME`, put `javac` on `PATH`, or specify it with `-JavaHome`;
- `build-tools;36.1.0` (aapt2, aapt, d8, zipalign, apksigner) and `platforms;android-36` (`android.jar`) from the Android SDK.
You can install them with the SDK's own `sdkmanager "build-tools;36.1.0" "platforms;android-36"`. Set the environment variable `ANDROID_HOME` (or `ANDROID_SDK_ROOT`)
You can install them with the SDK's own `sdkmanager "build-tools;36.1.0" "platforms;android-36"`. Reproducing v1.0.0 requires platform r2; SDK Manager may install a newer revision.
Set the environment variable `ANDROID_HOME` (or `ANDROID_SDK_ROOT`)
to the SDK root, or specify them directly with `-BuildTools` and `-AndroidJar`.

No Gradle. In the repository root:
Expand All @@ -114,6 +115,39 @@ No Gradle. In the repository root:
pwsh -NoProfile -File .\build.ps1
```

If Android 36 r2 is missing locally, or the SHA-256 of `platforms\android-36\android.jar` differs, download the pinned version from Google
and pass the extracted file with `-AndroidJar`. CI and release verification use the same fallback; a valid preinstalled file skips the download.

- Official metadata: [repository2-3.xml](https://dl.google.com/android/repository/repository2-3.xml), package `platforms;android-36`, revision `2`.
- Official archive: [platform-36_r02.zip](https://dl.google.com/android/repository/platform-36_r02.zip) (65,878,410 bytes).
- The metadata provides only SHA-1: `2c1a80dd4d9f7d0e6dd336ec603d9b5c55a6f576`. After checking that value, we computed and pinned the archive SHA-256:
`37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e`.
- Extracted `android-36\android.jar` SHA-256: `d9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a`.

Check the archive SHA-256 before extraction, then check the `android.jar` SHA-256. Either mismatch must stop the build. For example (using your local build-tools 36.1.0):

```powershell
$ErrorActionPreference = 'Stop'
$work = Join-Path ([IO.Path]::GetTempPath()) ("modavd-sdk-" + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $work | Out-Null
try {
$zip = Join-Path $work 'platform-36_r02.zip'
Invoke-WebRequest 'https://dl.google.com/android/repository/platform-36_r02.zip' -OutFile $zip
if ((Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash -ne '37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e') {
throw 'SDK archive SHA-256 mismatch'
}
Expand-Archive -LiteralPath $zip -DestinationPath $work
$jar = Join-Path $work 'android-36\android.jar'
if ((Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash -ne 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a') {
throw 'android.jar SHA-256 mismatch'
}
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar
if ($LASTEXITCODE -ne 0) { throw 'APK build failed' }
} finally {
Remove-Item -LiteralPath $work -Recurse -Force
}
```

- It first runs the protocol self-test `ProtocolTest` on the host JVM (`-SkipTest` skips it), then builds both APKs.
- The output goes to `out\`: `modavd-ime.apk`, `modavd-ime-testapp.apk`, `SHA256SUMS.txt`. Intermediate files are in `out\obj\` and are rebuilt every time. `-OutDir` changes the location.
- Signing uses the development key `out\keys\dev.p12` by default (its password is in `dev.p12.pass` in the same folder). If it does not exist, it is generated with the JDK's keytool.
Expand Down
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ CI(`ci.yml`)只在 Pull Request 和手动触发时跑:协议自测、在 W
- Windows 和 PowerShell 7.2 以上(`pwsh`);
- JDK 17 以上(维护者用 Temurin 25,`javac --release 17`):设 `JAVA_HOME`、把 `javac` 放进 `PATH`,或用 `-JavaHome` 指定;
- Android SDK 的 `build-tools;36.1.0`(aapt2、aapt、d8、zipalign、apksigner)和 `platforms;android-36`(`android.jar`),
可以用 SDK 自带的 `sdkmanager "build-tools;36.1.0" "platforms;android-36"` 装;设环境变量 `ANDROID_HOME`(或 `ANDROID_SDK_ROOT`)
可以用 SDK 自带的 `sdkmanager "build-tools;36.1.0" "platforms;android-36"` 装;复现 v1.0.0 需要 platform r2,SDK Manager 可能安装更新的 revision。
设环境变量 `ANDROID_HOME`(或 `ANDROID_SDK_ROOT`)
指向 SDK 根目录,或用 `-BuildTools`、`-AndroidJar` 直接指定。

不用 Gradle。在仓库根目录:
Expand All @@ -114,6 +115,39 @@ CI(`ci.yml`)只在 Pull Request 和手动触发时跑:协议自测、在 W
pwsh -NoProfile -File .\build.ps1
```

本地没有 Android 36 r2,或 `platforms\android-36\android.jar` 的 SHA-256 不符时,可以从 Google 下载固定版本,
用 `-AndroidJar` 指定解压后的文件。CI 和发版核对也用这个备用路径,预装文件校验正确时不下载。

- 官方元数据:[repository2-3.xml](https://dl.google.com/android/repository/repository2-3.xml),条目 `platforms;android-36`、revision `2`。
- 官方压缩包:[platform-36_r02.zip](https://dl.google.com/android/repository/platform-36_r02.zip)(65,878,410 字节)。
- 元数据只提供 SHA-1:`2c1a80dd4d9f7d0e6dd336ec603d9b5c55a6f576`;核对该值后计算并固定的压缩包 SHA-256:
`37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e`。
- 解压后的 `android-36\android.jar` SHA-256:`d9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a`。

先校验压缩包 SHA-256,再解压并校验 `android.jar` SHA-256;任一步失败都不能继续编译。例如(build-tools 仍用本地的 36.1.0):

```powershell
$ErrorActionPreference = 'Stop'
$work = Join-Path ([IO.Path]::GetTempPath()) ("modavd-sdk-" + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $work | Out-Null
try {
$zip = Join-Path $work 'platform-36_r02.zip'
Invoke-WebRequest 'https://dl.google.com/android/repository/platform-36_r02.zip' -OutFile $zip
if ((Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash -ne '37607369a28c5b640b3a7998868d45898ebcb777565a0e85f9acf36f29631d2e') {
throw 'SDK archive SHA-256 mismatch'
}
Expand-Archive -LiteralPath $zip -DestinationPath $work
$jar = Join-Path $work 'android-36\android.jar'
if ((Get-FileHash -LiteralPath $jar -Algorithm SHA256).Hash -ne 'd9eb9da824d9e247a352f570f01e1169e725b2954bca9e283a71786c59b59f9a') {
throw 'android.jar SHA-256 mismatch'
}
pwsh -NoProfile -File .\build.ps1 -BuildTools (Join-Path $env:ANDROID_HOME 'build-tools\36.1.0') -AndroidJar $jar
if ($LASTEXITCODE -ne 0) { throw 'APK build failed' }
} finally {
Remove-Item -LiteralPath $work -Recurse -Force
}
```

- 先在宿主 JVM 上跑协议自测 `ProtocolTest`(`-SkipTest` 跳过),再编两个 APK。
- 产物在 `out\`:`modavd-ime.apk`、`modavd-ime-testapp.apk`、`SHA256SUMS.txt`;中间文件在 `out\obj\`,每次重建。`-OutDir` 可改。
- 签名默认用开发密钥 `out\keys\dev.p12`(口令在同目录 `dev.p12.pass`),不存在就用 JDK 的 keytool 生成。
Expand Down
Loading