portal
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePortal
Portal
This skill is for building Android apps that target Meta's Portal device family. Portal devices are discontinued (sales stopped end of 2022), but ADB is now enabled, so owners can sideload their own apps.
The hardware: Snapdragon-based Android tablets and TV sticks running a modified AOSP without Google Mobile Services. Several models, all touch or TV. 28 (Android 9) or 29 (Android 10) depending on device.
minSdkVersionThis skill pairs with metavr (Meta VR CLI) — install it first. Use in place of raw everywhere. See for the one-line install (via ), the MCP-into-your-editor setup, and the Portal-relevant command surface. The full skill ships in the same repo and can also be loaded for deeper reference.
metavr adbadbresources/hzdb.mdnpxmetavr-cli本技能适用于构建针对Meta Portal设备系列的Android应用。Portal设备已停产(2022年底停止销售),但ADB现已启用,设备所有者可以侧载自己的应用。
硬件信息:基于骁龙芯片的Android平板和电视棒,运行修改版AOSP无Google移动服务(GMS)。包含多款型号,均支持触摸操作或为电视形态。不同设备对应的为28(Android 9)或29(Android 10)。
minSdkVersion本技能需搭配metavr(Meta VR命令行工具)使用——请先安装它。全程使用替代原生。如需一键安装(通过)、编辑器集成MCP配置,以及Portal相关命令说明,请查看。完整的技能位于同一仓库,也可加载以获取更详细参考。
metavr adbadbnpxresources/hzdb.mdmetavr-cliHard constraints — read before writing any code
硬性约束——编写代码前务必阅读
If you only remember a few things, remember these. Each is a class of bug Portal apps hit constantly.
- No Google Mobile Services. No Play Services, no Firebase, no FCM, no Play Billing, no Google Sign-In, no Google Maps SDK, no AdMob, no ML Kit. Apps with hard GMS deps will crash on launch. Pick non-GMS alternatives — see .
resources/app-requirements.md - is required (Portal hardware tops out at API 29). For new apps,
minSdkVersion ≤ 28is the safest default. For porting existing apps,targetSdkVersion 29higher than 29 usually works fine — verified empirically withtargetSdkVersion. Don't waste time downgrading the target SDK of an existing app unless you observe a concrete runtime issue.targetSdk = 36 - Launcher intent-filter is required. Touch devices need ; Portal TV needs
MAIN + LAUNCHER. TheMAIN + LEANBACK_LAUNCHERcategory is not required (verified empirically on Portal — apps with onlyDEFAULTappear on the home tile grid). Without one of these, the app installs but never appears on the home screen.MAIN + LAUNCHER - App icon must include a PNG in as a fallback. Declare
mipmap-xxxhdpi/(touch) orandroid:icon(TV) on the launcher activity. You can also ship adaptive icons (android:banner) and other density PNGs alongside — Portal's launcher correctly falls back to themipmap-anydpi-v26/PNG when the adaptive XML can't be rendered. Apps with only adaptive icons (no PNG fallback) will not have a visible icon on Portal.mipmap-xxxhdpi - No contacts API. No account/credentials API. is denied. The account provider returns nothing. 5a. Basic mic capture works; the far-field / beamformed mic array does not. Standard
READ_CONTACTSopens anRECORD_AUDIOstream and delivers real audio fromAudioRecord(the single-channel mic). The far-field beamformed array used by "Hey Portal" wake-word is gated by a Meta-signed native permission (handset-mic) and is not available to sideloaded apps. So basic voice features work; sideloaded wake-word detection and high-quality room-distance pickup do not. Seecom.facebook.alohasdk.permission.RECORD_AUDIO_PRIVILEGED§ Microphone capture for details.resources/app-requirements.md - Touch UI for tabletop, not phone form factor. Portal sits on a counter or stand. Users interact from 50–100 cm. Hit targets ≥ 64 dp (96 dp for primary actions), body text ≥ 16 sp (18 sp on Portal+), landscape-first. Full Portal design system (typography, spacing, palette, WCAG ratios, TalkBack rules) is in ; for Jetpack Compose apps,
resources/design-guidelines.mdis a copy-paste theme starter that bakes these rules intoresources/compose-theme.md/Color.kt/Theme.kt.Type.kt - Reserve the top ~64 dp (only if your top content sits within 64 dp of the canvas edge). Portal has a persistent system overlay strip at the top: back / home buttons (top-left) and Wi-Fi / status (top-right). It floats above app content with no automatic safe-area inset. Apps whose top UI hugs the edge (edge-to-edge toolbars, sticky headers, full-bleed modals) will tuck under it. Apps whose top content naturally sits ≥80 dp below the canvas edge don't need any change. The overlay pills are white, so apps with a light background in the top region need an additional dark scrim even after inset — see § Top system overlay.
resources/app-requirements.md
如果您只能记住几点,请牢记以下内容。这些是Portal应用经常遇到的各类问题。
- 无Google移动服务(GMS)。不支持Play服务、Firebase、FCM、Play Billing、Google登录、Google Maps SDK、AdMob、ML Kit。依赖GMS的应用会在启动时崩溃。请选择非GMS替代方案——详见。
resources/app-requirements.md - 必须满足(Portal硬件最高支持API 29)。对于新应用,
minSdkVersion ≤ 28是最安全的默认值。对于移植现有应用,targetSdkVersion 29高于29通常也能正常运行——已通过targetSdkVersion验证。除非观察到具体运行时问题,否则无需浪费时间降级现有应用的目标SDK。targetSdk = 36 - 必须配置启动器intent-filter。触摸设备需要;Portal TV需要
MAIN + LAUNCHER。无需MAIN + LEANBACK_LAUNCHER类别(已在Portal上验证——仅配置DEFAULT的应用会显示在主屏幕磁贴网格中)。如果缺少上述任一配置,应用会安装成功,但不会出现在主屏幕上。MAIN + LAUNCHER - 应用图标必须包含目录下的PNG作为回退。在启动器Activity上声明
mipmap-xxxhdpi/(触摸设备)或android:icon(电视设备)。您也可以同时提供自适应图标(android:banner)和其他密度的PNG——当无法渲染自适应XML时,Portal启动器会正确回退到mipmap-anydpi-v26/目录下的PNG。仅包含自适应图标(无PNG回退)的应用在Portal上不会显示可见图标。mipmap-xxxhdpi - 无联系人API,无账户/凭证API。权限会被拒绝。账户提供器返回空值。 5a. 基础麦克风采集可用;远场/波束成形麦克风阵列不可用。标准
READ_CONTACTS权限可打开RECORD_AUDIO流,并从AudioRecord(单声道麦克风)传输真实音频。“Hey Portal”唤醒词使用的远场波束成形阵列受Meta签名的原生权限(handset-mic)限制,无法供侧载应用使用。因此基础语音功能可用;侧载应用无法实现唤醒词检测和高质量远距离拾音。详情请见com.facebook.alohasdk.permission.RECORD_AUDIO_PRIVILEGED的「麦克风采集」章节。resources/app-requirements.md - 针对平板形态设计触摸UI,而非手机形态。Portal放置在柜台或支架上,用户从50–100厘米外交互。点击目标≥64 dp(主要操作≥96 dp),正文字体≥16 sp(Portal+上为18 sp),优先横向布局。完整的Portal设计系统(排版、间距、调色板、WCAG对比度、TalkBack规则)位于;对于Jetpack Compose应用,
resources/design-guidelines.md是可直接复制粘贴的主题模板,已将这些规则融入resources/compose-theme.md/Color.kt/Theme.kt。Type.kt - 预留顶部约64 dp空间(仅当您的顶部内容位于画布边缘64 dp范围内时需要)。Portal顶部有一个持久化系统覆盖条:返回/主页按钮(左上角)和Wi-Fi/状态栏(右上角)。它悬浮在应用内容上方,且不会自动添加安全区域内边距。顶部UI紧贴边缘的应用(全屏工具栏、粘性标题、全屏模态框)会被覆盖条遮挡。顶部内容自然位于画布边缘下方≥80 dp的应用无需任何更改。覆盖条按钮为白色,因此顶部区域为浅色背景的应用即使添加了内边距,也需要额外添加深色遮罩——详见的「顶部系统覆盖条」章节。
resources/app-requirements.md
Device matrix
设备矩阵
| 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 |
Set if you want to cover everything. If you don't need to support 1st-gen Portal / Portal+, you can target 29.
minSdkVersion 28| 设备 | | 连接方式 |
|---|---|---|
| Portal(第一代和第二代) | 28 / 29 | USB-C(背部) |
| Portal Mini | 29 | USB-C(背部) |
| Portal+(第一代和第二代) | 28 / 29 | USB-C(背部) |
| Portal Go | 29 | USB-C(背部橡胶盖下方) |
| Portal TV | 29 | USB-C |
如果想覆盖所有设备,请设置。如果无需支持第一代Portal/Portal+,可设置为29。
minSdkVersion 28Quickstart
快速开始
Toolchain first — don't hand-hunt for it. Building needs two host-machine pieces: a JDK (Gradle/AGP run on it) and the Android SDK. Install the SDK with Google's CLI — don't go scavenging the filesystem for an SDK. For the JDK, point at Android Studio's bundled JBR if Android Studio is installed, otherwise install Temurin 17. The CLI installs the SDK only — it does not provide a JDK. Full walkthrough: .
androidJAVA_HOMEandroidresources/android-sdk-setup.mdbash
undefined先配置工具链——不要手动查找。构建需要两台主机设备组件:JDK(Gradle/AGP运行依赖)和Android SDK。使用Google的命令行工具安装SDK——不要在文件系统中搜索SDK。对于JDK,如果已安装Android Studio,请将指向Android Studio捆绑的JBR;否则安装Temurin 17。命令行工具仅安装SDK——不提供JDK。完整教程:。
androidJAVA_HOMEandroidresources/android-sdk-setup.mdbash
undefined1) Get a JDK 17 (one-time, host machine — Gradle / AGP run on it; the android
CLI does NOT install one)
android1) 获取JDK 17(主机设备一次性操作——Gradle/AGP运行依赖;android
命令行工具不包含JDK)
androidIf Android Studio is installed, reuse its bundled JBR (no install needed):
如果已安装Android Studio,复用其捆绑的JBR(无需安装):
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
Otherwise install Temurin 17:
否则安装Temurin 17:
brew install --cask temurin@17 && export JAVA_HOME="$(/usr/libexec/java_home -v 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)
java -version # 应显示17.x(或使用Android Studio JBR时显示21.x)
2) Install Google's android
CLI (it manages the SDK), then install the SDK packages
android2) 安装Google的android
命令行工具(用于管理SDK),然后安装SDK包
androidmacOS: brew tap android/tap && brew install android-cli
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)
任意系统: curl -fsSL https://dl.google.com/android/cli/latest/darwin_arm64/install.sh | bash (其他系统请查看第1章节)
Windows: winget install --id Google.AndroidCLI
Windows: winget install --id Google.AndroidCLI
android update # keep the CLI current
android update # 保持命令行工具为最新版本
Install the SDK. For a new project: API 28 + 29. For porting, also install whatever compileSdk needs (often 35/36).
安装SDK。新项目:API 28 + 29。移植项目还需安装compileSdk所需的版本(通常为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
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使用~/Android/Sdk
3) Install metavr (one-time, host machine — requires Node.js 20+)
3) 安装metavr(主机设备一次性操作——需要Node.js 20+)
See resources/hzdb.md for full details and MCP-into-your-editor setup.
完整详情和编辑器集成MCP配置请查看resources/hzdb.md。
npx -y metavr --version
npx -y metavr --version
(or install globally)
(或全局安装)
npm install -g @meta-quest/metavr
npm install -g @meta-quest/metavr
4) Enable ADB on the Portal
4) 在Portal上启用ADB
Portal: Settings → Debug → ADB Enabled. Enter PIN if prompted.
Portal: 设置 → 调试 → 启用ADB。如有提示,输入PIN码。
Connect USB-C. Tap "Allow" on the device the first time you connect.
连接USB-C。首次连接时在设备上点击“允许”。
5) Verify
5) 验证
metavr device list
metavr device list
Should list one Portal device. Example: 819PGF02P010SL23 device Portal aloha
应列出一台Portal设备。示例:819PGF02P010SL23 device Portal aloha
(or npx -y metavr device list)
(或使用npx -y metavr device list)
6) Build + install + launch
6) 构建 + 安装 + 启动
No ./gradlew in the project? Bootstrap the wrapper first — see resources/android-sdk-setup.md § 0a.
项目中无./gradlew?先初始化wrapper——详见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
./gradlew assembleDebug
metavr app install -r app/build/outputs/apk/debug/app-debug.apk # -r/--replace 重新安装,保留数据
metavr app launch com.example.myapp # 或: metavr adb shell am start -n com.example.myapp/.MainActivity
(or use npx -y metavr instead of metavr if not globally installed)
(如未全局安装,使用npx -y metavr替代metavr)
If the device is missing from `metavr device list`, tap **ADB Enabled** on the Portal again — the toggle can race the USB connect.
如果`metavr device list`未显示设备,请再次点击Portal上的**启用ADB**——开关可能与USB连接冲突。Build configuration
构建配置
app/build.gradle.ktskotlin
android {
compileSdk = 35
defaultConfig {
minSdk = 28
targetSdk = 29
}
}compileSdk = 35app/build.gradle.ktskotlin
android {
compileSdk = 35
defaultConfig {
minSdk = 28
targetSdk = 29
}
}compileSdk = 35Manifest
清单文件
The launcher entry varies by device family.
Touch devices (Portal, Portal Mini, Portal+, Portal Go):
xml
<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>Portal TV (use and in place of ):
LEANBACK_LAUNCHERandroid:bannerandroid:iconxml
<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>Without these, the app installs but is invisible. To support both families from one APK, declare both intent filters on the same activity.
启动器配置因设备系列而异。
触摸设备(Portal、Portal Mini、Portal+、Portal Go):
xml
<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>Portal TV(使用和替代):
LEANBACK_LAUNCHERandroid:bannerandroid:iconxml
<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>缺少上述配置的话,应用会安装成功但不可见。如需通过一个APK支持两个设备系列,请在同一个Activity上声明两个intent-filter。
Permissions that work / don't work
可用/不可用权限
| 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 |
| 功能 | 状态 |
|---|---|
| 摄像头 | 支持常规 |
| 麦克风 | 支持常规 |
| 扬声器 | 无需权限 |
| 蓝牙 | 支持常规 |
| 网络 | 支持常规 |
| 触摸/键盘输入 | 无需权限 |
| 存储写入 | 支持常规 |
| 存储删除(跨应用) | 仅支持应用自有文件。否则:使用 |
联系人( | 不可用。运行时会被拒绝 |
设备账户( | 不可用。账户提供器返回空值 |
Smart Camera SDK (binary pending)
Smart Camera SDK(二进制包待发布)
Portal's camera is driven by a system Smart Camera service that owns face/body tracking, framing, and auto-pan-zoom to keep people in frame. Apps do not drive the camera directly with to get that behavior — they request a session from the Smart Camera service and pass a (auto-frame, desk framing, meeting framing, fixed crop, etc.).
Camera2ModeSpecA standalone Smart Camera SDK is in development. Planned Gradle coordinate: . Until the binary ships, see for the API sketch — same shape, same modes, same entry point.
com.facebook.portal:smartcamera:1.1.+resources/smart-camera-sdk.mdModeSpecSmartCameraControlConnectionFactoryRaw video frames are still available via the standard API; the Smart Camera SDK is for controlling the framing, not the pixels.
Camera2Portal的摄像头由系统级Smart Camera服务驱动,该服务负责面部/身体跟踪、取景,以及自动平移缩放以保持人物在画面中。应用无法直接使用驱动摄像头来实现上述行为——需向Smart Camera服务请求会话,并传递(自动取景、桌面取景、会议取景、固定裁剪等)。
Camera2ModeSpec独立的Smart Camera SDK正在开发中。计划的Gradle坐标:。在二进制包发布前,请查看获取API草图——形状一致,模式一致,入口一致。
com.facebook.portal:smartcamera:1.1.+resources/smart-camera-sdk.mdModeSpecSmartCameraControlConnectionFactory仍可通过标准 API获取原始视频帧;Smart Camera SDK用于控制取景,而非像素处理。
Camera2Debug loop
调试流程
bash
metavr 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 screenSee for more patterns and common failure modes (icon missing, app invisible after install, app crashes on first launch, etc.).
resources/debugging.mdbash
metavr adb logcat # 完整日志
metavr adb logcat *:E # 仅错误日志
metavr adb logcat -s AndroidRuntime DEBUG libc # 崩溃信号
metavr log -c # 清空日志缓冲区(注意:不是`metavr adb logcat -c`——该参数会被拒绝)
metavr adb shell dumpsys activity activities # 查看运行中的应用
metavr app clear com.example.myapp # 清除应用数据(或:metavr adb shell pm clear <pkg>)
metavr app uninstall com.example.myapp # 卸载应用
metavr capture screenshot -o screen.png # 保存屏幕截图为PNG更多模式和常见故障(图标缺失、安装后应用不可见、首次启动崩溃等)请查看。
resources/debugging.mdResources
资源
- — what metavr is, one-line install, MCP-into-your-editor, Portal-relevant commands
resources/hzdb.md - — full device prep walkthrough for a human user
resources/device-setup.md - — install JDK 17, Android CLI, SDK platforms / build-tools
resources/android-sdk-setup.md - — NDK / CMake / Ninja setup (use this when the project has native code; covers the deep-validation contract because
resources/native-toolchain.mdalone isn't enough)source.properties - — manifest, icons, no-GMS, design checklist (deep)
resources/app-requirements.md - — playbook for taking an existing Android app and getting it onto Portal (no-GMS flavor, native code, common failures)
resources/porting-existing-apps.md - — typography, spacing, color, accessibility, TV / D-pad, Smart Camera UX
resources/design-guidelines.md - — copy-paste Jetpack Compose theme starter (dark-forced theme, Portal palette, bundled-Inter typography, hit targets) with the no-GMS font fix
resources/compose-theme.md - — Smart Camera API surface (binary pending)
resources/smart-camera-sdk.md - —
resources/debugging.mdlogcat / screenshot / dumpsys patternsmetavr adb - — starter prompts to feed to Claude / Cursor / etc.
resources/sample-prompts.md
- —— metavr介绍、一键安装、编辑器集成MCP、Portal相关命令
resources/hzdb.md - —— 面向普通用户的完整设备准备教程
resources/device-setup.md - —— 安装JDK 17、Android CLI、SDK平台/构建工具
resources/android-sdk-setup.md - —— NDK/CMake/Ninja配置(项目包含原生代码时使用;涵盖深度验证规则,因为仅
resources/native-toolchain.md不够)source.properties - —— 清单文件、图标、无GMS、设计检查清单(详细)
resources/app-requirements.md - —— 将现有Android应用移植到Portal的指南(无GMS版本、原生代码、常见故障)
resources/porting-existing-apps.md - —— 排版、间距、颜色、无障碍、电视/方向键、Smart Camera UX
resources/design-guidelines.md - —— 可复制粘贴的Jetpack Compose主题模板(强制深色主题、Portal调色板、内置Inter字体、点击目标),包含无GMS字体修复
resources/compose-theme.md - —— Smart Camera API接口(二进制包待发布)
resources/smart-camera-sdk.md - ——
resources/debugging.md日志/截图/dumpsys模式metavr adb - —— 可用于Claude/Cursor等工具的初始提示词
resources/sample-prompts.md