关于 quest-native
面向使用 C 或 C++、OpenXR 和 Android 开发 Horizon OS 应用的 Agent 技能。它聚焦原生开发中容易出错的兼容边界,并要求在采用 API 和配置前核对 Meta 文档。
主要功能
- 01判断项目适用的开发技术路线
- 02核验 Meta API 与文档
- 03配置开发和发布 manifest
- 04处理 SDK 级别与 OpenXR 加载器
- 05实现会话、帧循环与焦点规则
- 06按能力检测设备功能
适用场景
- 01检查原生 Quest 项目的 manifest
- 02排查 OpenXR 加载器启动问题
- 03实现焦点切换时持续渲染
- 04确认 Horizon OS API 和 SDK 要求
MCP 相关
技能通过 metavr MCP 服务搜索 Meta 文档;该服务提供与 CLI 相同的文档搜索能力。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ssheleg/ xr-dev --skill quest-native安装后在 Claude Code 中输入/quest-native确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/doc-map.mdframe-loop.mdmanifest-and-gradle.mdmixed-reality.mdproject-playbook.md详细介绍
Horizon OS 上的原生 OpenXR
使用 C 或 C++ 编写的 Quest 应用通过 OpenXR 与头显通信,并通过 Android 与底层的手机级操作系统通信。大多数问题都出在这两者的衔接处:清单文件在侧载时合法、在商店审核时却不合法;加载器版本导致崩溃,而不是降级运行;一旦失去焦点,帧循环就停止绘制。
阅读 references/project-playbook.md,了解项目探索、目标/版本约定、引擎交接、纵向切片和审计。阅读 references/mixed-reality.md,了解功能/权限决策、追踪/空间生命周期、同地协作,以及摄像头或 AI 输入。
如果要规划整个产品路线图或进行阶段审计,请使用 quest-lifecycle;单个技术任务仍由本技能负责。如果该技能不存在,请直接指出当前阶段、相关证据和下一个前置条件。
步骤 0——这个项目真的适用这条路径吗?
| 项目类型 | 负责方 |
|---|---|
| 使用 C / C++、面向 OpenXR,采用 Gradle + NDK | 本技能 |
| Unity | Meta 的 hz-unity-* 技能(共 12 个:核心 SDK、MRUK、移动/重定向、quest-ui、透视摄像头、放置、平台 SDK、项目分析器、TMP、FBX 导入、面部追踪、代码审查) |
| Unreal | https://developers.meta.com/horizon/llmstxt/documentation/unreal/llms.txt/ |
| Kotlin / Spatial SDK | Meta 的 hz-spatial-sdk |
| WebXR、IWSDK、PWA | 本工具包中的 quest-webxr |
| 现有的 2D Android 应用 | Meta 的 hz-android-2d-porting |
选错路径造成的损失比本文档中的任何单个 bug 都大:Unity 相关的解答无法直接用于 NativeActivity,OpenXR 扩展名称也无法直接用于 Unity 的 OVR 封装。
步骤 1——先验证,再回答
Horizon OS 按自己的节奏发布,API 表面也随之变化。凡是涉及 Quest API、所需 SDK 级别或清单元素的说法,在写入代码之前都要先对照 Meta 官方文档核验:
metavr docs search "openxr swapchain" # the CLI; the MCP server exposes the same search
每个文档页面都有对应的 Markdown 版本——无需抓取 HTML,也无需登录:
index: https://developers.meta.com/horizon/llmstxt/documentation/native/llms.txt/
page: https://developers.meta.com/horizon/llmstxt/documentation/native/android/<slug>.md
references/doc-map.md 收录了值得牢记的文档 slug。如果已安装 Meta 的 hz-quest-verify-first 技能,它会自行执行此项检查——请查看其结果,而不要重复搜索。
步骤 2——清单文件,其实有两套
开发要求和发布要求有所不同,审核时只会强制检查发布要求(VRC.Quest.Packaging.1、.4)。编写开发用清单文件并提交,却不检查发布要求的差异,可能导致审核失败。
沉浸式 OpenXR 应用当前的 Meta 清单片段(已于 2026-09-21 重新核验):
<uses-feature android:name="android.hardware.vr.headtracking"
android:required="true" android:version="1" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="com.oculus.intent.category.VR" />
</intent-filter>
android.hardware.vr.headtracking中的required="true"会将应用标记为沉浸式应用;2D 面板应用应省略此项或将其设为required="false"。android:screenOrientation="landscape"、主题Theme.Black.NoTitleBar.Fullscreen,以及清单文档列出的完整configChanges列表。绝不要使用noHistory。- 仅发布时:
android:debuggable设为 false 或省略,installLocation="auto",使用唯一的android:label,并通过com.oculus.supportedDevices列出quest2|questpro|quest3|quest3s——不在该列表中的设备会以兼容模式运行,并将自身报告为较旧一代设备。 - 纯 NativeActivity 应用可以使用
android:hasCode="false"发布。Platform SDK 是一个 Java 库;添加它后就不能再使用该选项。
完整的逐项约定以及两套清单的并列对照:
references/manifest-and-gradle.md。
步骤 3 — SDK 级别:2026 年发生了变化
适用于仍受支持的设备(Quest 2、Pro、3 系列)的推荐设置:minSdk 32、
targetSdk 34、compileSdk ≥ targetSdk。合法范围为 minSdk 29–34,沉浸式应用的
targetSdk 为 32–34(2D 面板应用为 32–36)——但自 2026 年 3 月 1 日起创建的应用必须以 34 为目标版本。固定这些值之前,请先阅读源文件中的两张表;表格附有日期,见
references/manifest-and-gradle.md。
锁定文件不等于构建配置。 搜索 build.gradle 和项目使用的所有依赖锁定文件:2026-09-20,在某个 Quest 项目中,gradle 写的是
targetSdk 34,而 dependencies.lock.json 仍写着 32。这份发行说明描述的是一个并不存在的构建。
步骤 4 — 加载器,以及任何代码之前必须启用的两个扩展
android { buildFeatures { prefab true } }
dependencies { implementation 'org.khronos.openxr:openxr_loader_for_android:<ver>' }
- Meta 支持 Khronos Android 加载器;已不存在专有加载器。低于 1.0.34 时应用会崩溃——不会回退到其他加载器。
- 使用 Khronos 加载器的应用在低于 v62 的 Horizon OS 上会崩溃,而 v62 以下的非 Quest 1 用户永远不会在 Store 中看到更新。
XR_KHR_loader_init_android:通过xrGetInstanceProcAddress并使用空实例获取xrInitializeLoaderKHR,使用XrLoaderInitInfoAndroidKHR调用它,然后才能创建任何对象。XR_KHR_android_create_instance:Android 专属参数通过此扩展传入xrCreateInstance。
步骤 5 — 能通过审核的帧循环
- 使用
xrPollEvent驱动会话;由状态机而非布尔值决定何时开始和结束会话。 xrWaitFrame→xrBeginFrame→ 渲染 →xrEndFrame,并根据等待返回的预测显示时间设置所有姿态。对着“现在”进行渲染,即使配置文件干净,也会产生抖动。- 关注焦点是 VRC 要求,而非锦上添花(
VRC.Quest.Input.4):应用失去焦点时仍需继续渲染、隐藏手部和控制器,并忽略输入。在系统菜单打开时冻结的应用无法通过审核。 - 使用
xrEnumerateSwapchainFormats枚举交换链格式,并从返回结果中选择;硬编码格式迟早会造成兼容性问题。颜色空间必须显式指定(XR_FB_color_space),不能假定默认值。 - 仅支持 64 位二进制文件(
VRC.Quest.Packaging.6);APK 小于 1 GB,OBB 小于 4 GB (.5)。
会话状态、帧节奏和焦点规则详见:references/frame-loop.md。
步骤 6 — 检查功能,不要依赖设备型号
通过所选 SDK/运行时检查功能,而不只是判断“是不是 Quest Pro”。OpenXR 扩展枚举只是其中一层;还可能需要系统属性、权限、账户限制和有效的追踪状态。Camera2 功能不能简化为 OpenXR 扩展名称。兼容模式可能会改变报告的型号,因此仅检查设备名称并不足够。
此技能提供的后续指引
| 后续问题 | 位置 |
|---|---|
| 可以运行,但会丢帧 | quest-perf(帧预算、GPU% 陷阱、捕获工具) |
| 如何将其安装到头显/读取日志 | quest-tooling(metavr CLI + MCP、adb、模拟器) |
| 如何发布 | quest-store(渠道、VRC、DUC、上传) |
| 改用 WebXR 或 PWA 构建 | quest-webxr |
让你多花一轮时间调试的注意事项
- 开发清单通过侧载,但审核失败。 两份文档对应两套要求;发布版位于
resources/publish-mobile-manifest。 - 启动类别错误可能看起来像渲染错误。当前 Meta 发布页面指定
com.oculus.intent.category.VR;请根据该页面和所选 SDK 检查合并后的 APK,而不是照搬通用的 OpenXR 代码片段。 - 低于 1.0.34 的 Loader 会在启动时崩溃,且没有任何诊断信息指向 Loader。
hasCode="false"与 Platform SDK 互不兼容——权益检查(VRC.Quest.Security.1,这是建议而非要求)会让原生应用引入 Java。- 示例是最快获得正确答案的途径。
hello_xr(Khronos)和 Meta 的 OpenXR SDK 示例——XrPassthrough、XrSceneModel、XrHandsAndControllers、XrSpaceWarp、XrSpatialAnchor、XrVirtualKeyboard——分别端到端演示一个扩展。手动编写扩展前,请先阅读示例。
以上文档信息摘自 developers.meta.com,日期为 2026-09-20;引用具体数字前,请使用 metavr docs search 重新核实。
触发词
还有一些会将请求路由到此处的短语:“Quest C++”/“Quest 用 C++”,“VR 的 AndroidManifest”/“VR 清单”,“openxr_loader_for_android”,“xrWaitFrame”,“Quest 的 targetSdk”/“Quest 的 targetSdk 是多少”,“IMMERSIVE_HMD”,“hello_xr”,“原生应用中的 passthrough”/“原生 passthrough”。
此处内容于 0.4.4 从描述中移入:“Quest 原生应用”。