diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d462cb..f10c84e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ project follows [Semantic Versioning](https://semver.org/). - **Analytics validation runbook.** Documented native Matomo live validation, expected event payloads, and the current web/WASM analytics split. +- **Android smoke-test runbook.** Updated the Android doc with the current + platform status and a physical-device launch/touch/safe-area checklist. - **Browser Bevy canvas route and automation support.** Added the `solitaire_web` Bevy WASM build, wired `/play` to the Bevy canvas, added a `window.__FERROUS_DEBUG__` bridge, and introduced Playwright coverage for the diff --git a/SESSION_HANDOFF.md b/SESSION_HANDOFF.md index 3fe38fc..583e919 100644 --- a/SESSION_HANDOFF.md +++ b/SESSION_HANDOFF.md @@ -104,16 +104,9 @@ Three bugs fixed: ### 1. Android APK launch verification (Option A) Physical device test: install the latest APK on a real Android device (not AVD), -confirm: -- App launches without crash -- Safe area insets arrive and shift HUD correctly after ~3 frames -- All modal Done buttons are above the gesture bar -- Drag-and-drop works on all pile types -- Leaderboard panel opens and the "Public name" label updates correctly after - using "Set Name" - -This has never been gated in CI. AVD `adb shell input tap` doesn't deliver real -touch events, so physical-device smoke testing is the only gate. +and run the checklist in `docs/ANDROID.md`. This has never been gated in CI. +AVD `adb shell input tap` doesn't deliver real touch events, so physical-device +smoke testing is the only gate. ### 2. Matomo analytics live validation diff --git a/docs/ANDROID.md b/docs/ANDROID.md index 91f0fb6..cd21aa0 100644 --- a/docs/ANDROID.md +++ b/docs/ANDROID.md @@ -5,10 +5,10 @@ Android target. Steps are runnable on a fresh Debian 13 (trixie) box; later sections document what's known to compile, what's stubbed, and the next milestones. -> **Status (2026-05-07):** First working APK at `fb8b2ac`. 54 MB -> debug-signed `ferrous-solitaire.apk` for `x86_64-linux-android`. Has -> NOT yet been verified to launch on a device or emulator — that's -> the next milestone. +> **Status (2026-06-09):** Android build plumbing, app-directory storage, +> JNI keystore wiring, and safe-area layout fixes have landed. The remaining +> release gate is a physical-device smoke test; AVD tap injection does not +> exercise the real touch path reliably enough for launch verification. --- @@ -163,8 +163,8 @@ accepted workaround. Physical device: ```bash -adb devices # confirm connection -adb install target/debug/apk/ferrous-solitaire.apk +adb devices # confirm connection +adb install -r target/debug/apk/ferrous-solitaire.apk adb shell am start -n com.ferrousapp.solitaire/android.app.NativeActivity adb logcat | grep -iE "RustStdoutStderr|solitaire|panic" ``` @@ -185,35 +185,65 @@ AVD. --- -## 4. What's wired vs. what's stubbed +## 4. Physical-device smoke test -The first build pass (commit `fb8b2ac`) gates four desktop-only -crates / call sites so the workspace cross-compiles. Each gate is -documented at its call site. +Run this on a real phone, preferably a modern 64-bit ARM device with gesture +navigation enabled. + +Build and install: + +```bash +cargo apk build -p solitaire_app --target aarch64-linux-android --lib +adb install -r target/debug/apk/ferrous-solitaire.apk +adb logcat -c +adb shell am start -n com.ferrousapp.solitaire/android.app.NativeActivity +adb logcat | grep -iE "RustStdoutStderr|solitaire|panic|WindowInsets" +``` + +Pass criteria: + +- App launches without panic or ANR. +- Safe-area insets arrive after the first few frames and shift HUD/modal + content away from the status and gesture bars. +- Every modal's Done button remains above the gesture bar: + Settings, Help, Pause, Win Summary, and Leaderboard-related dialogs. +- Drag-and-drop works on tableau, waste, foundation, and stock/recycle paths. +- Tap-to-select and one-tap modes both respond correctly on card stacks. +- Leaderboard panel opens, "Set Name" saves, and the "Public name" label updates + while the panel remains open. +- Rotate the device once, then repeat one modal and one drag operation. +- Close and relaunch the app; settings/progress still load. + +Record the device model, Android version, APK commit, and pass/fail notes in the +release notes or session handoff. If a failure occurs, keep the filtered logcat +and note the exact screen/control path that reproduced it. + +--- + +## 5. What's wired vs. what's stubbed + +Desktop-only crates and call sites are gated so the workspace cross-compiles. +Each gate is documented at its call site. | Surface | Desktop | Android | |---------|---------|---------| | Bevy windowing | x11 + wayland | `android-native-activity` (NativeActivity glue) | | Clipboard ("Copy share link") | `arboard` writes URL | Toast surfaces the URL inline | -| OS keychain (JWT tokens) | `keyring` v4 → Secret Service / Keychain / Credential Store | Stub returning `KeychainUnavailable`; sync requires fresh login each launch | +| OS keychain (JWT tokens) | `keyring` v4 → Secret Service / Keychain / Credential Store | Android Keystore via JNI | +| Data directory | Platform data dir | Android app files dir | | App entry point | `bin` target → `solitaire_app::run()` | `cdylib` target loaded by NativeActivity | -What's NOT yet ported / not yet measured: +What's not yet ported / not yet measured: -- `dirs::data_dir()` returns `None` on Android. Callers in - `solitaire_data/src/storage.rs`, `progress.rs`, `replay.rs`, - `achievements.rs`, `settings.rs` all need an Android-aware - helper (likely `/data/data/com.ferrousapp.solitaire/files`). - Touch UX pass — hit-target sizes, modal scaling on small screens, app lifecycle (suspend / resume), font scaling. -- Android Keystore via JNI for `auth_tokens`. - JNI ClipboardManager for share links. - Google Play Games sign-in (the `solitaire_gpgs` crate referenced in older docs doesn't yet exist). --- -## 5. Iteration loop +## 6. Iteration loop ```bash # Edit code…