Skip to content

ibrahimokdadov/mobiler

Repository files navigation

Mobiler

A lightweight Android emulator for Expo and React Native developers, built with Tauri v2, QEMU, and Android-x86.

Read before using: This project has fundamental performance limitations that make it unsuitable for daily development. See Limitations below.

What it is

Mobiler boots Android-x86 9.0 inside QEMU and wraps it in a small Tauri desktop app. The goal was to give React Native and Expo developers a lighter alternative to Android Studio's emulator, which consumes 4+ GB of RAM and takes minutes to boot.

The Tauri shell is ~5MB. Android boots in roughly 60 seconds. ADB connects automatically over TCP.

Stack

  • Desktop shell: Tauri v2 (Rust + React 19 + TypeScript)
  • Styling: Tailwind CSS 3
  • State: Zustand v5
  • Virtualization: QEMU with WHPX (Windows) / HVF (macOS) / KVM (Linux)
  • Android: Android-x86 9.0-r2
  • Display: VNC over WebSocket
  • Device bridge: ADB over TCP

Prerequisites

  • QEMU installed and on PATH (or placed in src-tauri/bin/)
  • Android Platform Tools (ADB)
  • An Android-x86 9.0-r2 disk image (.qcow2) — see setup below
  • Rust 1.80+ and Node.js 18+
  • Windows: Hyper-V / Windows Hypervisor Platform enabled

Setup

1. Install dependencies

npm install

2. Get QEMU and ADB binaries

Run the helper script, or place the binaries manually in src-tauri/bin/:

bash scripts/download-sidecars.sh

3. Prepare the Android disk image

bash scripts/prepare-android-image.sh

This downloads the Android-x86 9.0-r2 ISO (~900MB), creates a 16GB QCOW2 disk, and walks you through the installer. After install, extract the kernel and initrd next to the image file.

4. Run

npm run tauri dev

Limitations

This section exists so you know what you are getting into before spending time on it.

Performance

The single biggest problem is rendering. Mobiler uses software rendering: Android's compositor draws every frame using the CPU, which gets encoded by VNC and sent over a WebSocket to a browser canvas. The pipeline looks like this:

Android CPU rendering -> VGA framebuffer -> VNC encode -> WebSocket -> browser canvas

Every UI frame goes through at least four transformations. Scrolling feels slow. Google's Android emulator avoids this entirely by using GPU passthrough via ANGLE, which is only available in their custom QEMU fork, not in upstream QEMU.

Slow disk I/O

Android-x86's init script only scans /dev/sd* paths for storage, which means the disk must use the emulated IDE interface instead of the faster virtio-blk. This slows down every app install, file read, and asset load.

Slow network

The network card uses the emulated e1000 adapter instead of the faster paravirtualized virtio-net, for compatibility during early boot. Metro bundler transfers (JS bundles can be 10-50MB) are noticeably slower than on a physical device.

No GPU passthrough

Without virgl or a native display backend, there is no OpenGL ES acceleration in apps. Maps, 3D UI, animations, and any app using hardware-accelerated rendering will either be very slow or fail entirely.

WHPX limitations (Windows)

On Windows, QEMU uses WHPX (Windows Hypervisor Platform). WHPX is measurably slower than KVM (Linux) or HVF (macOS) for the same guest workload. It also requires kernel-irqchip=off, which degrades interrupt handling inside the VM.

32-bit apps do not work

Under WHPX, 32-bit processes crash due to a bug in how the hypervisor handles vDSO (the virtual system call interface). The fix is to boot Android in 64-bit-only mode by patching the zygote configuration before boot. This means any app or library that ships 32-bit native code will not run.

Cold boot every time

There is no snapshot support. Every launch boots Android from scratch, which takes approximately 60 seconds on decent hardware.

Android 9 only

Android-x86 9.0-r2 targets API level 28 (Android 9). Apps that require API level 30+ (Android 11) or use newer APIs may crash. Google's official emulator ships Android 14 images — a five-year gap in SDK coverage.

No audio

Audio is disabled in the QEMU configuration. Apps that depend on audio output will fail silently.

Single instance only

The VM manager is a global singleton. Only one emulator instance can run at a time.


Known workarounds built in

Zygote64 patch — On boot, Mobiler intercepts the Android init sequence via the serial console and patches default.prop to set ro.zygote=zygote64 before Android starts. This bypasses the 32-bit zygote crash under WHPX. The side effect is that 32-bit ABIs are disabled entirely.

IDE disk interface — The disk uses if=ide instead of if=virtio because Android-x86's init script does not load virtio-blk drivers early enough to find the disk at /dev/vda.

e1000 network — The network card uses e1000 instead of virtio-net-pci for broader boot compatibility.


What to use instead

If you want a lightweight Android testing setup for Expo or React Native:

Physical device (recommended) — Scan the QR code from the Expo CLI. The app loads over your local network in seconds. No virtualization, no boot time, real GPU, real touch input.

Official Android emulator with a minimal AVD — Create a device without Google Play, 2GB RAM cap, animations disabled. Still heavier than Mobiler in binary size, but actually usable for development.

BlueStacks / LDPlayer — Gaming emulators with real GPU passthrough and fast boot. Not developer-oriented, but fine for quick visual checks.


Architecture

src/
  components/
    controls/     # VM start/stop controls
    display/      # VNC canvas viewer
    setup/        # First-run setup wizard
    status/       # VM status indicators
  store/
    vm-store.ts        # VM state (Zustand)
    settings-store.ts  # Persistent settings
    sensor-store.ts    # Sensor simulation state
  App.tsx

src-tauri/src/
  qemu/
    manager.rs    # QEMU process lifecycle
    config.rs     # VM configuration and QEMU args
    accel.rs      # Hardware acceleration detection (WHPX/HVF/KVM/TCG)
  adb/
    bridge.rs     # ADB connection
    commands.rs   # ADB shell commands
    port_forward.rs
  display/
    scrcpy_server.rs  # scrcpy server push/start (partial)
  expo/
    detect.rs     # Metro bundler detection
    setup.rs      # Expo Go install/launch
  sensors/        # Sensor simulation
  commands/       # Tauri IPC command handlers

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors