Android Horizon

Docs

Setup, controls, architecture, and building from source.

Setup

  1. Grab the latest bundled release zip from the Releases page and drag its contents onto your SD card's /switch/ folder.
  2. Place .apk files in sdmc:/AndroidHorizonNX/apks/.
  3. Launch AndroidHorizonNX from hbmenu (Atmosphere CFW required).
  4. Navigate with D-pad, left stick, or touch; press A or tap a game to launch it.
  5. If a launch fails, check sdmc:/AndroidHorizonNX/compat_log.txt for the full error log.

Controls

Handheld mode only. Android games use touch screen input. The Switch touchscreen only works in handheld mode — in docked mode there is no touch input, so games will be uncontrollable. Android Horizon detects docked mode and shows a warning in the footer.
InputAction
D-pad / left stick / swipeNavigate the APK list
A / tap a gameLaunch selected APK
XReinstall + launch (re-extracts the APK)
YRescan the APK folder
About screen (credits, scrollable via D-pad/stick/touch)
+Quit
BBack (on result/about screens)

Architecture — launcher + Translation Core

Android Horizon is split into two pieces, in two separate repos, that chain-load into each other rather than being one monolithic binary:

Why split it this way: a Switch process runs in one execution state (AArch64 or AArch32) for its whole lifetime, so the picker and a hypothetical future 32-bit engine can't be one process. Splitting the picker from the engine means adding a real 32-bit engine later is "point the launcher at a new NRO," not "rewrite everything." Splitting them into separate repos keeps the launcher (small, stable) decoupled from the engine (where almost all development happens) — "the app won't launch" and "the game crashes" issues land in the right place.

Building from source

Requires devkitPro with devkitA64 and libnx installed.

Android Horizon is split across two repositories as well as two NRO binaries — clone both as siblings to build everything and get a drag-to-SD-card layout:

export DEVKITPRO=/opt/devkitpro
git clone https://github.com/AndroidHorizon/AndroidHorizonNX.git
git clone https://github.com/AndroidHorizon/AHNX-Translation-Core.git
cd AndroidHorizonNX
./build_all.sh

Output: testingbuild/AndroidHorizonNX.nro (copy to sdmc:/switch/) and testingbuild/AndroidHorizonNX/ (copy the whole folder to sdmc:/switch/AndroidHorizonNX/).

Just want the launcher on its own? make in the AndroidHorizonNX repo builds AndroidHorizonNX.nro by itself.

Dependencies (via pacman/devkitPro)

switch-sdl2 switch-sdl2_image switch-sdl2_ttf
switch-libpng switch-libjpeg-turbo switch-minizip
switch-mesa switch-glad switch-curl switch-mbedtls

Prebuilt releases (no toolchain needed) are published on the Releases page — each one bundles the launcher plus both Translation Core builds, ready to drag onto an SD card. Releases are built and published automatically by a GitHub Actions workflow (manually triggered by org staff) that also generates an in-depth changelog and refreshes the in-app contributor credits from every repo in the org.

Forwarders — a dedicated home-menu icon per game

Android Horizon can boot straight into one specific game, skipping the app-list picker entirely — the same idea as a RetroArch forwarder that jumps straight into a ROM+core instead of RetroArch's own content browser.

Pass the game's package name (e.g. com.fingersoft.hillclimb) as the first argument when launching AndroidHorizonNX.nro. This uses libnx's standard envSetNextLoad(path, argv) chain-load mechanism — the same one homebrew forwarders (RetroArch included) use. If the requested package isn't installed, Android Horizon falls back to the normal app-list picker with an on-screen notice.

Submitting a compatibility report

Tried a game and want it on the compatibility page? Use the submission form — no GitHub account needed. Attach the .apk you tested directly (uploads straight to storage — real APKs running 50-150MB are no problem) or paste a download link, say where you got it from, and attach or paste the three log files from sdmc:/AndroidHorizonNX/: launcher_log.txt, compat_log.txt, and <package>/log.txt. There's no length limit on the log fields either way.

It's handled entirely by automation, and there's no maintainer in the loop:

  1. The form posts to a small relay (a Cloudflare Worker) that queues the submission in compat-reports and kicks off a GitHub Action — no GitHub login involved anywhere in this step.
  2. The APK is fetched, validated, and sanity-checked as a real ZIP.
  3. Its package name, version, display name, and icon are read straight out of the manifest — not typed in, so they can't drift from what was actually tested.
  4. The Play Store listing is checked to confirm it's actually a game.
  5. The three logs are scanned for frame stalls, crash/error signatures, and whether the game ever rendered a frame at all, producing a verdict: Playable, Runs with issues, Fails to launch, or Inconclusive.
  6. The result — logs, a generated report, the APK's SHA-256, and an icon — is published to compat-reports and shows up on the compatibility page within a few minutes. A repeat submission for the same package+version replaces the previous one.

If you gave a GitHub username, it shows up on the Credits page and in the launcher's own About screen under Testers — that field isn't verified, it's just for display.

More

The full technical history — every root-caused bug, every hardware measurement, the complete changelog — lives in the AndroidHorizonNX README.