Support Android 17 (target=37, api_level=37) in build + integration tests - #53
Conversation
reactivecircus/android-emulator-runner@v2 interpolates its `api-level` and `target` inputs directly into the sdkmanager package names it installs. For Android 17 Google only publishes feature-drop variants (`platforms;android-37.0` / `-37.1`) under `google_apis` etc. — no bare `platforms;android-37` and no `default` tag exist at API 37 — so passing "37.0" and "google_apis" through to the action makes it request packages that actually exist. Minimal reproduction of the Android-17 CI workaround: this branch carries only the two workflow-input mappings, without the AGP 9.1.1 / Gradle 9.3.1 bump or cmdline-tools 22 upgrade. Purpose is to confirm which pieces are strictly required. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AGP 8.2.2 cannot resolve `compileSdk = 37` — it looks for
`platforms;android-37` on disk, which Google no longer publishes for
Android 17 (feature-drop naming: only `platforms;android-37.0` /
`-37.1` exist). AGP 9.1.1 is Google's first line that maps
`compileSdk = 37` to the installed feature-drop platform.
Both projects (Kotlin + Java):
* AGP `com.android.tools.build:gradle` 8.2.2 -> 9.1.1
* Gradle wrapper 8.2 -> 9.3.1 (AGP 9.1.1 minimum)
* `proguard-android.txt` -> `proguard-android-optimize.txt` — AGP 9
rejects the non-optimized default because it embeds `-dontoptimize`,
which prevents R8 optimizations.
Kotlin project only:
* Drop `org.jetbrains.kotlin:kotlin-gradle-plugin` classpath and
`ext.kotlin_version` — AGP 9 ships built-in Kotlin support.
* Drop `id 'kotlin-android'` from `app/build.gradle` plugins block.
* Move `android.kotlinOptions { jvmTarget = "1.8" }` to top-level
`kotlin { compilerOptions { jvmTarget = JVM_1_8 } }`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Without this, avdmanager v12 (pre-installed on ubuntu-latest) doesn't understand the SDK XML v4 metadata that ships with feature-drop system-images and writes `target=android-0` into the AVD's config.ini. The emulator then can't finish booting — sits in "device offline" until reactivecircus/android-emulator-runner@v2 hits the 600s boot timeout. Empirically confirmed on run 30365450517 (this branch, cancelled at ~5 min stuck in adb-poll loop): "Warning: This version only understands SDK XML versions up to 3 but an SDK XML file of version 4 was encountered" fires during `avdmanager create avd`, and boot never completes. Runs only for `api_level == '37'` so older api-levels are untouched. Pending upstream: ReactiveCircus/android-emulator-runner#483. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ReviewCI + build config only, so nothing to check against a ticket. The diff is small (+43/-12) and the reasoning is unusually well evidenced. I verified the two claims the description presents as "coupled AGP 9 requirements" — both are genuinely forced, not discretionary:
Also checked the one unchecked test-plan box: it's satisfied. This PR touches Overall: approve with comments. Nothing blocks merge. One security hardening item and one workflow-robustness item are worth fixing now; the publisher-facing impact of the AGP bump deserves an explicit decision. Strengths
🟡 1.
|
Two issues surfaced in the PR #53 review: 1. `api_level=37.0` on workflow_dispatch silently took the non-37 path (target=default, cmdline-tools upgrade skipped) — reproduces the 600s emulator-boot hang the PR was written to fix. Fix: compute a single `is_android_17` step output for the "is this A17?" decision from a case matching `37`, `37.0`, `37.1`, and gate both the emulator-runner inputs and the cmdline-tools upgrade step on it. One source of truth. 2. cmdline-tools zip was downloaded and unzipped without an integrity check. Add sha1sum verification against Google's published digest for build 15859902 (040d3996a65543d22ec4bf73e4c37aa37a8d4af4). Also move `working-directory` to `/tmp` so the archive doesn't land in the checkout root and can't dirty the workspace on abort. Plus a README note: the AGP 8 -> 9 bump raises the floor for any publisher who copies these demo apps. Document the AGP 9.1+ / Gradle 9.3+ / JDK 17+ requirement and point at JetBrains' migration guide so publishers on AGP 8 know what to expect. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a small markdown table to $GITHUB_STEP_SUMMARY summarizing which LevelPlay SDK version, emulator API level, target tag, and compile/ target SDK the job actually ran against. Renders as a header at the top of the run's Summary page so it's obvious per matrix job without digging into step logs or artifact names. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Unblocks the Android integration-tests workflow for Android 17 / target=37 / api_level=37 across both matrix jobs (Kotlin + Java). Verified end-to-end green on GHA: run 30366238885 — Kotlin ~4:40, Java ~4:38.
Three commits, each isolating a distinct required piece — deltas kept minimal:
api_level=37in the workflow toapi-level: "37.0"+target: "google_apis"when callingreactivecircus/android-emulator-runner@v2. Older api-levels pass through unchanged withtarget: default.kotlin-androidplugin,kotlin { compilerOptions {} }block).$ANDROID_HOME/cmdline-tools/latestto build 15859902 (cmdline-tools 22.0). Runs only whenapi_level == '37'.Why each piece is required (verified empirically)
Google switched Android 17 to a feature-drop release model. Only versioned variants of the SDK packages exist:
platforms;android-37— not publishedplatforms;android-37.0,platforms;android-37.1— publishedsystem-images;android-37;<tag>;<abi>— not publishedsystem-images;android-37.0;google_apis;<abi>— published (nodefaulttag exists at API 37)Failed to find Platform SDK with path: platforms;android-37(AGP 8.2.2 can't mapcompileSdk = 37to the on-diskplatforms/android-37.0/)api-level: "37.0"Warning: Failed to find package 'platforms;android-37'target: "google_apis"Warning: Failed to find package 'system-images;android-37.0;default;x86_64'SDK XML file of version 4 was encountered; avdmanager writestarget=android-0into AVDconfig.ini; emulator boot never completes and reactivecircus times out at 600sAll 4 pieces present ⇒ end-to-end green: run 30366238885.
Behavior for older API levels
Unchanged. The workflow-input mapping only rewrites
api_level=37; anything else passes through as before. The cmdline-tools upgrade step hasif: ${{ steps.args.outputs.api_level == '37' }}and is a no-op otherwise. Runs at defaultapi_level=29are byte-identical to before this PR.Removes when
Both upstream PRs land and we bump the reactivecircus action pin:
Once those release in a fresh
@v2or@v3, the workflow mappings and cmdline-tools install step can be removed and the reactivecircus block goes back to the original 4-line form. The AGP + Gradle bump stays (it's an inherent AGP requirement forcompileSdk = 37, unrelated to the action).Supersedes
Replaces PR #52, which had the same fix mixed with two dead-end experiment commits (manual emulator setup) that aren't needed.
Test plan
./gradlew assembleDebug(default target 34) passes on both projects../gradlew assembleDebug -PtargetSdkVersion=37 -PcompileSdkVersion=37passes on both projects,aapt2 dump badgingconfirmstargetSdkVersion:'37'../gradlew connectedDebugAndroidTest -PtargetSdkVersion=37 -PcompileSdkVersion=37— 6/6 tests pass on an API 37 arm64-v8a emulator (Kotlin + Java).sdk_version=9.5.0 api_level=37 target_sdk_version=37— run 30366238885, both matrix jobs green.🤖 Generated with Claude Code