skills/hz-android-2d-porting/SKILL.md
Guides porting existing Android 2D apps to Meta Quest and Horizon OS — input adaptation, panel layout, and design requirements. Use when adapting a mobile Android app for Quest.
npx skillsauth add meta-quest/agentic-tools hz-android-2d-portingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when:
Horizon OS is built on Android (AOSP) and can run standard Android applications inside panels -- floating 2D windows positioned in 3D space. Most well-built Android apps work on Quest with minimal changes, but several areas require attention:
The goal of porting is to make the app feel native to the Quest experience while preserving existing functionality.
Invoke hzdb (the Quest device CLI) via npx -y @meta-quest/hzdb <args> — no global install needed; npx fetches the latest published version on demand.
If using npx, use npx -y @meta-quest/hzdb as an alternative to calling hzdb found in this doc.
Install the existing APK on a connected Quest device and test basic functionality:
hzdb app install path/to/your-app.apk
hzdb app launch com.example.yourapp
Note any immediate issues: crashes, black screens, input problems, or layout breakage.
The most common porting issue is input. Touch events are translated from the controller pointer, but:
See Input Adaptation Reference for detailed guidance.
Panels are resizable and can have various aspect ratios. Your app must handle:
Use responsive layout strategies such as ConstraintLayout or Jetpack Compose. See Panel Layout Reference.
Update your build configuration to target Horizon OS:
// build.gradle.kts
android {
defaultConfig {
minSdk = 29 // Android 10 minimum
targetSdk = 34 // API 34 or higher required for all new 2D panel apps
}
}
Add required manifest entries for device targeting. See Gradle Setup Reference.
Test with all supported input methods:
Use the XR Simulator for rapid iteration, then validate on-device.
Before submitting to the Horizon Store:
| Feature | Status | Notes | |---|---|---| | Standard Android Views | Supported | TextView, RecyclerView, etc. | | Jetpack Compose | Supported | Full Compose UI toolkit | | WebView | Supported | Chromium-based | | Media playback (ExoPlayer) | Supported | Video and audio | | Networking (HTTP, WebSocket) | Supported | Wi-Fi connectivity | | Room / SQLite | Supported | Local database | | WorkManager | Supported | Background tasks | | Notifications | Supported | Horizon OS notification panel | | Bluetooth (peripherals) | Supported | Keyboard, mouse, gamepad | | Android Accessibility APIs | Supported | TalkBack equivalent available |
| Feature | Status | Notes | |---|---|---| | Camera (front-facing) | Not available | No standard camera in 2D mode | | Telephony / SMS | Not available | No cellular radio | | NFC | Not available | No NFC hardware | | GPS / Fine location | Limited | Wi-Fi-based location only | | Fingerprint / BiometricPrompt | Not available | Use Meta account auth instead | | Split-screen (multi-window) | Limited | Use Spatial SDK panels instead | | Google Play Services | Not available | Use Meta equivalents or alternatives | | ARCore | Not available | Use Meta Spatial SDK for spatial features | | Multi-touch gestures | Limited | Single pointer from controller |
| Issue | Cause | Fix |
|---|---|---|
| App crashes on launch | Missing Google Play Services dependency | Remove or make GMS optional |
| Buttons too small to tap | Touch targets under 48dp | Increase minimum tap target size |
| No scroll in lists | Swipe-based scroll not triggered | Ensure RecyclerView/LazyColumn handles generic scroll events |
| Keyboard doesn't appear | Custom input field not using InputConnection | Use standard EditText or TextField |
| Layout broken | Fixed-size layout assumptions | Use responsive layouts with ConstraintLayout or Compose |
| App requests unavailable permissions | Camera, telephony, etc. | Guard with hasSystemFeature() checks |
| APK rejected for prohibited permissions | Library or plugin silently added a prohibited permission | Run aapt dump permissions your-app.apk, then check prohibited list |
| APK rejected for invalid signature | Signed with v1-only scheme | v2 signing is default in AGP 7.0+; for older AGP, add v2SigningEnabled = true to your signing config |
Apps not specifically targeting Horizon OS run in compatibility mode:
Apps that target Horizon OS with proper manifest entries run in native mode:
Quest devices have mobile-class hardware with strict thermal limits:
development
Build and sideload Android apps for Meta Portal devices (Portal, Portal+, Portal Mini, Portal Go, Portal TV) using hzdb. Use when targeting Portal hardware — covers ADB enablement, the no-GMS constraint, manifest/launcher intent-filter requirements, icon density quirks (PNG-only, mipmap-xxxhdpi), the Smart Camera SDK, and the gradle + `hzdb adb` build/deploy/debug loop. Auto-load when the user mentions "Portal" device, targets `minSdkVersion` 28-29 for a tabletop/TV form factor, or works with the `com.facebook.portal` package.
tools
Provides the complete hzdb (Horizon Debug Bridge) CLI reference for Meta Quest and Horizon OS development — installation, device setup, command discovery, MCP server mode, documentation search, app deployment, device testing setup, audio control, screenshots, and performance analysis. Use when the user needs to install hzdb, asks what commands are available, needs CLI syntax help, or wants to know what hzdb can do.
development
Sets up the Meta XR Simulator for testing Meta Quest and Horizon OS apps without a physical device. Use when configuring device-free testing for Unity or Unreal projects.
development
Validates Meta Quest and Horizon OS apps against VRC (Virtual Reality Check) store publishing requirements. Use when preparing a build for Quest Store submission or running pre-submission compliance checks.