release-android: workaround wry getId() ProGuard regression (#8)#11
Merged
Conversation
`wry <= 0.55.0` ships a `proguard-wry.pro` template that's missing `int getId();` from the WryActivity keep block. R8 strips the Kotlin auto-generated getter (no Java/Kotlin code calls it), then tao 0.35's JNI bridge calls `activity.getId()` at onActivityCreate, gets a NoSuchMethodError, panics, and the APK crashes before its first frame. Upstream fix: tauri-apps/wry#1721 (merged 2026-05-04, awaiting release). This workaround stays in place until the next wry release flows in transitively, then this whole step gets deleted. The workaround has to deal with two sharp edges: 1. `cargo tauri android build --apk` regenerates `proguard-wry.pro` from wry's bundled template every run, so we can only patch it between init and the next R8 invocation. 2. Gradle's R8 task does not declare the proguard file as an input, so editing it in place doesn't invalidate R8's incremental cache. We have to wipe R8 outputs to force a re-run. Sequence: build → patch (idempotent, errors if the regex doesn't match the current wry template) → wipe R8/dex outputs → re-run gradle's `:app:assembleUniversalRelease` excluding the rust-build tasks (the `.so`s are already built; running rust tasks via gradle standalone fails because they invoke `cargo tauri` which needs a parent WebSocket). Final dex sanity-check confirms the patched `getId()` actually landed inside the WryActivity class block. Codex review surfaced four findings, all addressed: - [P1] Original dex grep matched any `getId` in the dex (RustWebView also has one), so a stripped WryActivity.getId could pass. Now scoped via awk to the WryActivity class block. - [P1] Sanity check used to silently skip if APK or dexdump was missing. Both are now hard errors. - [P1] dexdump emits class descriptor lines with leading spaces, so the awk's class-end anchor `^Class descriptor` never matched and in_block stayed true past WryActivity. Anchor now uses `^[[:space:]]*Class descriptor`. - [P3] `find ... | head -n1` under pipefail risks SIGPIPE; switched to `find ... -print -quit` with an explicit search-root guard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #8.
Summary
Workaround in `release-android.yml` for the wry ProGuard regression
that crashes the Android APK at first launch with `tao 0.35` panicking
in `onActivityCreate`. Verified end-to-end on a Pixel 6 / Android 14
emulator: the patched APK launches into the chat shell.
Background: codex-validated investigation in
issue #8.
Upstream fix is tauri-apps/wry#1721
— merged today, awaiting a wry release. This workflow change goes away
the moment that release flows in transitively (the patch step is
idempotent and emits a `::notice::` if it sees the upstream fix already
in place).
What the new step does
Inserted between `Build APK` and `Sign APKs`:
proguard file as an input, so we have to bust the cache)
four rust-build tasks (`.so`s are already built; running them via
gradle standalone fails because they invoke `cargo tauri` which
needs a parent WebSocket)
landed in the dex (scoped to the WryActivity class block — a
false-positive on the unrelated `RustWebView.getId` would otherwise
pass).
Codex review chain
sanity check, find/pipefail)
leading whitespace → class-end anchor was wrong → in_block leaked
past WryActivity)
Test plan
through, produces a debug-signed universal APK
`INSTALL_PARSE_FAILED_NO_CERTIFICATES`
`onActivityCreate` panic)
emits `::notice::` and exits the patch path early, build still
succeeds