Loading...
Loading...
Build and sideload Android apps for Meta Portal devices (Portal, Portal+, Portal Mini, Portal Go, Portal TV) using metavr. 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 + `metavr 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.
npx skill4agent add meta-quest/agentic-tools portalminSdkVersionmetavr adbadbresources/hzdb.mdnpxmetavr-cliresources/app-requirements.mdminSdkVersion ≤ 28targetSdkVersion 29targetSdkVersiontargetSdk = 36MAIN + LAUNCHERMAIN + LEANBACK_LAUNCHERDEFAULTMAIN + LAUNCHERmipmap-xxxhdpi/android:iconandroid:bannermipmap-anydpi-v26/mipmap-xxxhdpiREAD_CONTACTSRECORD_AUDIOAudioRecordhandset-miccom.facebook.alohasdk.permission.RECORD_AUDIO_PRIVILEGEDresources/app-requirements.mdresources/design-guidelines.mdresources/compose-theme.mdColor.ktTheme.ktType.ktresources/app-requirements.md| Device | | Connection |
|---|---|---|
| Portal (1st and 2nd gen) | 28 / 29 | USB-C (back) |
| Portal Mini | 29 | USB-C (back) |
| Portal+ (1st and 2nd gen) | 28 / 29 | USB-C (back) |
| Portal Go | 29 | USB-C (under rubber cover on back) |
| Portal TV | 29 | USB-C |
minSdkVersion 28androidJAVA_HOMEandroidresources/android-sdk-setup.md# 1) Get a JDK 17 (one-time, host machine — Gradle / AGP run on it; the `android` CLI does NOT install one)
# If Android Studio is installed, reuse its bundled JBR (no install needed):
# export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
# Otherwise install Temurin 17:
# brew install --cask temurin@17 && export JAVA_HOME="$(/usr/libexec/java_home -v 17)"
java -version # should report 17.x (or 21.x if using Android Studio JBR)
# 2) Install Google's `android` CLI (it manages the SDK), then install the SDK packages
# macOS: brew tap android/tap && brew install android-cli
# Any OS: curl -fsSL https://dl.google.com/android/cli/latest/darwin_arm64/install.sh | bash (see § 1 for other OSes)
# Windows: winget install --id Google.AndroidCLI
android update # keep the CLI current
# Install the SDK. For a new project: API 28 + 29. For porting, also install whatever compileSdk needs (often 35/36).
android sdk install platforms/android-28 platforms/android-29 platform-tools build-tools/34.0.0
export ANDROID_HOME="$HOME/Library/Android/sdk" # macOS — Linux uses ~/Android/Sdk
# 3) Install metavr (one-time, host machine — requires Node.js 20+)
# See resources/hzdb.md for full details and MCP-into-your-editor setup.
npx -y metavr --version
# (or install globally)
npm install -g @meta-quest/metavr
# 4) Enable ADB on the Portal
# Portal: Settings → Debug → ADB Enabled. Enter PIN if prompted.
# Connect USB-C. Tap "Allow" on the device the first time you connect.
# 5) Verify
metavr device list
# Should list one Portal device. Example: 819PGF02P010SL23 device Portal aloha
# (or npx -y metavr device list)
# 6) Build + install + launch
# No ./gradlew in the project? Bootstrap the wrapper first — see resources/android-sdk-setup.md § 0a.
./gradlew assembleDebug
metavr app install -r app/build/outputs/apk/debug/app-debug.apk # -r/--replace reinstalls, keeping data
metavr app launch com.example.myapp # or: metavr adb shell am start -n com.example.myapp/.MainActivity
# (or use npx -y metavr instead of metavr if not globally installed)metavr device listapp/build.gradle.ktsandroid {
compileSdk = 35
defaultConfig {
minSdk = 28
targetSdk = 29
}
}compileSdk = 35<activity
android:name=".MainActivity"
android:icon="@mipmap/ic_launcher"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>LEANBACK_LAUNCHERandroid:bannerandroid:icon<activity
android:name=".MainActivity"
android:banner="@drawable/banner"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>| Capability | Status |
|---|---|
| Camera | Regular |
| Microphone | Regular |
| Speaker | No permission needed |
| Bluetooth | Regular |
| Network | Regular |
| Touch / keyboard input | No permission needed |
| Storage write | Regular |
| Storage delete (cross-app) | App-owned only. Otherwise: |
Contacts ( | Not available. Denied at runtime |
Device accounts ( | Not available. Account provider returns nothing |
Camera2ModeSpeccom.facebook.portal:smartcamera:1.1.+resources/smart-camera-sdk.mdModeSpecSmartCameraControlConnectionFactoryCamera2metavr adb logcat # full logcat
metavr adb logcat *:E # errors only
metavr adb logcat -s AndroidRuntime DEBUG libc # crash signals
metavr log -c # clear the log buffer (NOT `metavr adb logcat -c` — that flag is rejected)
metavr adb shell dumpsys activity activities # what's running
metavr app clear com.example.myapp # wipe app data (or: metavr adb shell pm clear <pkg>)
metavr app uninstall com.example.myapp # uninstall
metavr capture screenshot -o screen.png # save a PNG of the screenresources/debugging.mdresources/hzdb.mdresources/device-setup.mdresources/android-sdk-setup.mdresources/native-toolchain.mdsource.propertiesresources/app-requirements.mdresources/porting-existing-apps.mdresources/design-guidelines.mdresources/compose-theme.mdresources/smart-camera-sdk.mdresources/debugging.mdmetavr adbresources/sample-prompts.md