feat(dev): an Android failure looks exactly like a success
The APK installs and launches. It also dies six milliseconds later, and finding that out cost a cycle for three reasons that have nothing to do with the bug itself: **Go's stdout does not reach logcat.** An Android app's fd 1 and 2 go to /dev/null, so every slog line -- including the one naming the error the app is about to exit on -- is discarded. `setprop log.redirect-stdio true` does not help: that redirects the Java runtime's System.out, and our code is a c-shared native library. **os.Exit leaves no evidence.** No panic, no AndroidRuntime stack, nothing in /data/tombstones, nothing in `logcat -b crash` or dropbox. All three places anyone would look are empty, and the one signal that is present -- "Zygote: exited due to signal 9" -- reads as "the system killed it" and sends you after the low-memory killer. **ActivityManager restarts it faster than you can observe.** pidof always answers and `am start` always reports Status: ok, so a crash-looping app looks alive. "Did it start" is the wrong question; `make android-smoke` asks whether it is the *same pid* N seconds later, and prints the filtered logcat plus how to read it when it is not. The tell, once known: "I/WailsBridge: Wails bridge initialized" followed immediately by a new pid doing the same thing. scripts/android-emulator.sh follows dev-headless.sh's shape -- background start, saved-PID stop, filtered log tail, never pkill -f. Two scaffold tasks are deliberately not wrapped: `android:logs` greps logcat for (Wails|yellowjacket), which catches the WailsBridge tag but misses the app's own process tag (app.yellowjacket is lowercase) and misses ActivityManager's "has died" line, which is the one that says it crashed; and `ensure-emulator` boots whatever `-list-avds | tail -1` returns, with no pidfile and no boot wait, so it cannot be sequenced. One environment note that is not obvious on Arch: Gradle needs a platform and /opt/android-sdk has none, so ANDROID_SDK defaults to ~/Android/Sdk while ANDROID_NDK points at /opt/android-ndk. Two SDKs, one for each half of the build.
This commit is contained in:
@@ -151,6 +151,7 @@ only climb when it cannot.
|
||||
| Something you cannot predict — exploring | `make dev-headless SEED=default` + `playwright-cli` | interactive |
|
||||
| Something whose answer is a *number*, not a pass | `make perf` against a bulk-seeded app | ~1 min + setup |
|
||||
| A `.sql` or `.templ` file | `make generate`, then the checklist in [references/schema-change.md](references/schema-change.md) | |
|
||||
| Anything that has to survive on a phone | `make android-smoke` against a booted emulator | ~1 min + setup |
|
||||
|
||||
Two targets are once-per-clone prerequisites that are **not**
|
||||
dependencies of the targets needing them, so on a fresh checkout each
|
||||
@@ -426,3 +427,9 @@ fails the build otherwise, including in files no lint pass compiles.
|
||||
and what breaks in it.
|
||||
- [schema-change.md](references/schema-change.md) — the two-file
|
||||
schema/migration checklist.
|
||||
- [android-tier.md](references/android-tier.md) — the emulator tier,
|
||||
and the three reasons a failure there looks like a success. **Read
|
||||
its first section before running anything on Android**: Go's stdout
|
||||
does not reach logcat, `os.Exit` leaves no panic and no tombstone,
|
||||
and ActivityManager restarts a dying app fast enough that `pidof`
|
||||
always answers.
|
||||
|
||||
Reference in New Issue
Block a user