-
Notifications
You must be signed in to change notification settings - Fork 8
Native Android
FEBuilderGBA has an experimental native Android port built on the cross-platform Avalonia GUI. It is a real APK that runs the shared Avalonia UI on-device — not the Windows desktop build running under an x86 emulation layer.
Authoritative reference: the full, evidence-backed design and status lives in the in-repo
docs/ANDROID.md. This page is a summary.
- A
FEBuilderGBA.Android/application head that builds and packages a signed APK consuming the same Avalonia views as the desktop GUI. - The shared
FEBuilderGBA.Avaloniaproject multi-targetsnet10.0;net10.0-android. - Built on top of
FEBuilderGBA.Core(platform-independent) +FEBuilderGBA.Avalonia(shared UI). WinForms is not Android-capable and is excluded.
The android target framework is opt-in and OFF by default, so the desktop solution and all desktop CI keep seeing net10.0 only and are completely untouched:
dotnet workload install android
dotnet build FEBuilderGBA.Android/FEBuilderGBA.Android.csproj -c Release -p:EnableAndroidTarget=trueThe -p:EnableAndroidTarget=true global property is required so NuGet restore cross-targets the shared project too. The Android head is deliberately excluded from FEBuilderGBA.sln — the required desktop build check runs the whole solution on a Windows runner with no android workload, so adding the head to the .sln would break unrelated PRs.
| Area | How it works |
|---|---|
config/ bundling |
The config/ tree ships as an AndroidAsset and is version-stamped, extracted on first run to the app's FilesDir, so the app finds its game-data definitions without a desktop-style working directory. |
| ROM file I/O |
Stream-based via Avalonia IStorageProvider / Android SAF (Storage Access Framework), since Android content:// picks have no plain file path. Loads rewind the stream; seekable saves truncate. |
| Navigation | The desktop multi-window model is replaced by a single-activity shell: an INavigationService + single-view host routes the editor-launch call sites through a page/view-stack on Android. |
| SkiaSharp pin |
SkiaSharp.NativeAssets.Android is pinned to 2.88.x to match Avalonia's bundled native Skia — a 3.x managed package against an 88.x native crashes inside the Avalonia process. |
The rendering pipeline is validated byte-identical on a real Android emulator. The CI workflow android-emulator-parity.yml runs the SkiaSharp render byte-parity + version-guard tests on an API-34 x86_64 emulator on every push/PR to master, using a direct reflection test runner (.NET 10 Android embeds test assemblies as .so, so xUnit's on-disk discovery doesn't apply). A second advisory workflow (android.yml) builds the APK and uploads it as an artifact. Both are non-blocking by design (separate job contexts from the required build check) so a slow/flaky Android job can never block a desktop PR merge.
The honest status: the APK builds and the render pipeline is emulator-validated for parity. The remaining frontier is full on-device UX:
- Touch interaction and per-editor attached-
Windowdialogs are not yet fully reworked for a phone form factor. -
arm64-v8a/armeabi-v7aare covered by the same SkiaSharp package (same upstream Skia build, ABI-specific binaries) but are not directly emulated on GitHub-hosted x86_64 runners.
See docs/ANDROID.md for the layer-by-layer capability assessment, the phased roadmap, and the build prerequisites.
-
docs/ANDROID.md— authoritative, full detail - Native iOS — the sibling mobile head (shares all the runtime seams)
- Native Web — the WebAssembly head (shares the same seams; runs in a browser)
- Avalonia GUI — the shared cross-platform frontend the Android head consumes
- Getting Started — platforms & downloads