Android Setup — Build & Run on Emulator
This guide walks through every step to get a Vue Native app building and running on the Android Emulator, from prerequisites to hot reload.
Prerequisites
| Tool | Version | Install |
|---|---|---|
| Android Studio | Ladybug+ | developer.android.com/studio |
| Android SDK | API 35 | Via Android Studio SDK Manager |
| JDK | 17 | Bundled with Android Studio |
| Bun (or Node 18+) | 1.3+ | curl -fsSL https://bun.sh/install | bash |
Android Studio setup
After installing Android Studio:
- Open Settings > Languages & Frameworks > Android SDK
- Under SDK Platforms, check Android 15 (API 35)
- Under SDK Tools, check:
- Android SDK Build-Tools 35.x
- Android Emulator
- Android SDK Platform-Tools
- Click Apply to download
Set ANDROID_HOME
Add to your shell profile (~/.zshrc or ~/.bashrc):
export ANDROID_HOME=$HOME/Library/Android/sdk # macOS
export PATH=$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator:$PATH
Reload your shell: source ~/.zshrc
Create an emulator
- In Android Studio: Tools > Device Manager > Create Virtual Device
- Pick a device (e.g. Pixel 8)
- Select a system image:
- API 35, x86_64 (Intel/AMD) or arm64 (Apple Silicon)
- Finish
Or via CLI:
sdkmanager "system-images;android-35;google_apis;arm64-v8a"
avdmanager create avd -n Pixel8 -k "system-images;android-35;google_apis;arm64-v8a"
Verify:
emulator -list-avds # should list your AVD
adb --version # Android Debug Bridge
Quick start (CLI)
The fastest path — the CLI handles everything:
# 1. Scaffold project
npx @thelacanians/vue-native-cli create my-app
cd my-app
bun install
# 2. Boot emulator (in background)
emulator -avd Pixel8 &
# 3. Build JS bundle + build APK + install + launch
vue-native run android
vue-native run android does all of the following automatically:
- Runs
vite buildto producedist/vue-native-bundle.js - Copies the bundle to
android/app/src/main/assets/ - Runs
./gradlew assembleDebug - Installs the APK via
adb install - Launches the app via
adb shell am start
If you want to understand what happens under the hood, read on.
Step-by-step (manual)
1. Create and scaffold
npx @thelacanians/vue-native-cli create my-app
cd my-app
bun install
This generates:
my-app/
app/ # Vue 3 source
main.ts
App.vue
pages/Home.vue
android/ # Native Gradle project
build.gradle.kts # Root Gradle config (AGP 8.7.3, Kotlin 2.0.21)
settings.gradle.kts # Includes :app, repositories
gradle.properties # JVM args, AndroidX flags
gradle/wrapper/ # Gradle 8.11.1 wrapper
gradlew # Gradle wrapper script
app/
build.gradle.kts # App module: compileSdk 35, minSdk 24
proguard-rules.pro
src/main/
AndroidManifest.xml
assets/ # JS bundle goes here
kotlin/.../MainActivity.kt
res/values/strings.xml
res/values/themes.xml
res/xml/network_security_config.xml
src/debug/res/xml/
network_security_config.xml # Allows cleartext for dev server
dist/ # Built JS bundle (generated)
vite.config.ts
vue-native.config.ts
package.json
2. Build the JS bundle
bun run build
This runs Vite with the Vue Native plugin. It:
- Compiles
.vueSFCs via@vitejs/plugin-vue - Aliases
vueimports to@thelacanians/vue-native-runtime(the native renderer) - Outputs a single IIFE file:
dist/vue-native-bundle.js - Target: ES2020 (V8/J2V8 on Android supports this)
3. Copy the bundle to assets
mkdir -p android/app/src/main/assets
cp dist/vue-native-bundle.js android/app/src/main/assets/
Automate this
Add a Gradle task to copy the bundle automatically before each build:
// android/app/build.gradle.kts
tasks.register<Copy>("copyJsBundle") {
from("../../dist/vue-native-bundle.js")
into("src/main/assets")
}
tasks.named("preBuild") { dependsOn("copyJsBundle") }
4. Build the APK
cd android
./gradlew assembleDebug
This:
- Downloads Gradle 8.11.1 (first run only)
- Resolves dependencies from Google, Maven Central, JitPack, and GitHub Packages
- Compiles Kotlin sources
- Links the VueNativeCore library
- Packages the JS bundle from
assets/ - Signs with the debug keystore
- Outputs:
app/build/outputs/apk/debug/app-debug.apk
First build is slow
The first build downloads Gradle + all dependencies (~2-3 min). Subsequent builds are incremental and much faster.
5. Boot the emulator
# Start the emulator in background
emulator -avd Pixel8 &
# Wait for it to be ready
adb wait-for-device
6. Install and launch
# Install the APK
adb install -r android/app/build/outputs/apk/debug/app-debug.apk
# Launch the app
adb shell am start -n "com.vuenative.myapp/.MainActivity"
Your app should appear on the emulator.
Using Android Studio directly
You can also build and run from Android Studio's GUI:
- Open the
android/directory as a project - Wait for Gradle sync to complete
- Select your emulator from the device dropdown (top toolbar)
- Click the Run button (green triangle) or press Shift+F10
Android Studio handles the build, install, and launch. Logcat (bottom pane) shows [VueNative] log output.
Hot reload
Hot reload lets you edit .vue files and see changes instantly without rebuilding the APK.
Setup
Terminal 1 — Start the dev server:
bun run dev
This starts:
- Vite in watch mode (rebuilds
dist/vue-native-bundle.json every save) - A WebSocket server on
ws://localhost:8174
Terminal 2 — Run the app (first time only):
vue-native run android
Or build from Android Studio. Once the app is running, you don't need to rebuild — changes are pushed via WebSocket.
How it works
- You save
app/pages/Home.vue - Vite detects the change, rebuilds
vue-native-bundle.js - The dev server sends the new bundle over WebSocket
HotReloadManagerin the app receives itJSRuntimetears down the old V8 context, creates a new one, evaluates the new bundle- UI updates on screen
Emulator networking
The Android emulator maps 10.0.2.2 to the host machine's localhost. The scaffolded MainActivity.kt already has this configured:
class MainActivity : VueNativeActivity() {
override fun getBundleAssetPath() = "vue-native-bundle.js"
override fun getDevServerUrl(): String? {
return if (BuildConfig.DEBUG) "ws://10.0.2.2:8174" else null
}
}
For a physical device on the same WiFi network, use your machine's LAN IP:
override fun getDevServerUrl(): String? {
return if (BuildConfig.DEBUG) "ws://192.168.1.100:8174" else null
}
Or use adb reverse to forward ports over USB:
adb reverse tcp:8174 tcp:8174
# Now the device can connect to ws://localhost:8174
Debugging
Logcat
All console.log() / console.error() calls from your Vue code appear in Logcat:
# Filter to Vue Native logs
adb logcat -s VueNative-JSRuntime:* VueNative-Bridge:* VueNative-HotReload:*
Or in Android Studio: open the Logcat tab and filter by VueNative.
Error overlay
In debug builds, unhandled JS errors display a red overlay on screen with the error message and stack trace.
Checking the bundle loaded
If you see a white screen, verify the bundle is executing:
// Add to the top of app/main.ts
console.log('Bundle executing')
Then check Logcat. If you see the log, the bundle loaded. If not, check:
- The bundle exists at
android/app/src/main/assets/vue-native-bundle.js bun run buildcompleted without errors
Useful adb commands
# List connected devices/emulators
adb devices
# View all logs (verbose)
adb logcat
# Clear logcat
adb logcat -c
# Take a screenshot
adb exec-out screencap -p > ~/Desktop/screenshot.png
# Open a URL (deep linking)
adb shell am start -a android.intent.action.VIEW -d "myapp://settings"
# Uninstall the app
adb uninstall com.vuenative.myapp
# Forward ports (for physical device hot reload)
adb reverse tcp:8174 tcp:8174
Common issues
"SDK location not found" — Create android/local.properties:
sdk.dir=/Users/yourname/Library/Android/sdk
Or set the ANDROID_HOME environment variable (see Prerequisites).
"Could not resolve com.eclipsesource.j2v8:j2v8" — J2V8 is hosted on JitPack. Verify jitpack.io is in the repositories block in settings.gradle.kts:
maven { url = uri("https://jitpack.io") }
White screen — The most likely causes:
- Bundle not copied to
assets/— runbun run buildthen copy - Dev server URL incorrect — emulator uses
10.0.2.2, notlocalhost - Check Logcat for
[VueNative]errors
"INSTALL_FAILED_NO_MATCHING_ABIS" — CPU architecture mismatch. Use an x86_64 system image on Intel/AMD, or arm64 on Apple Silicon. Check your emulator image matches your machine.
Emulator can't connect to dev server — The emulator uses 10.0.2.2 to reach the host. Verify:
bun run devis running on the host- Nothing else is using port 8174:
lsof -i :8174 getDevServerUrl()returns"ws://10.0.2.2:8174"
Gradle build OOM — Increase heap in gradle.properties:
org.gradle.jvmargs=-Xmx4096m
Dependency conflicts — Inspect the dependency tree:
cd android && ./gradlew :app:dependencies
See the Troubleshooting guide for more.