expo-horizon
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExpo Horizon: Migrating Expo SDK to Meta Quest
Expo Horizon:将 Expo SDK 迁移至 Meta Quest
Software Mansion's production guide for adding Meta Quest support to Expo apps using the expo-horizon packages.
This skill does not bundle a copy of the docs. For any task below, always webfetch the linked official README or Meta documentation page to get up-to-date installation steps, plugin options, API surface, and feature matrices. This skill only captures the decision tree, critical rules, and non-obvious gotchas that agents routinely miss.
Software Mansion 出品的生产级指南,介绍如何使用 expo-horizon 包为 Expo 应用添加 Meta Quest 支持。
本技能未包含文档副本。 对于以下任何任务,请务必联网获取链接中的官方 README 或 Meta 文档页面,以获取最新的安装步骤、插件选项、API 接口和功能矩阵。本技能仅涵盖决策流程、关键规则以及智能体常忽略的隐性陷阱。
Decision Tree
决策流程
What do you need to do?
│
├── Starting from scratch or adding Quest support to an existing Expo app?
│ └── Follow the "Setup Workflow" below (do NOT auto-install location or
│ notifications packages) and webfetch: expo-horizon-core README
│ ├── Install expo-horizon-core
│ ├── Configure the config plugin (horizonAppId, panel size, supportedDevices)
│ ├── Add quest/mobile build scripts
│ ├── Add runtime device detection (isHorizonDevice, isHorizonBuild)
│ └── Detect expo-location / expo-notifications, then ASK before migrating
│
├── Need location services on Quest?
│ └── Webfetch: expo-horizon-location README
│ ├── Replace expo-location with expo-horizon-location
│ ├── Review the feature support matrix
│ └── Guard unsupported calls (heading, geocoding, geofencing, background)
│
├── Need push notifications on Quest?
│ └── Webfetch: expo-horizon-notifications README
│ ├── Replace expo-notifications with expo-horizon-notifications
│ ├── Configure horizonAppId in expo-horizon-core
│ ├── Use getDevicePushTokenAsync (Expo Push Service is not supported)
│ └── Skip badge counts (not supported on Quest)
│
└── Need to build, run, or publish for Quest?
└── Webfetch: expo-horizon-core README (build variants) + Meta docs below
├── Build variants: questDebug, questRelease, mobileDebug, mobileRelease
├── Meta Quest Developer Hub (device management, sideloading)
└── Meta Horizon Store manifest requirements你需要完成什么操作?
│
├── 从零开始开发,还是为现有 Expo 应用添加 Quest 支持?
│ └── 遵循下方的「设置流程」(请勿自动安装定位或通知包)并联网获取:expo-horizon-core README
│ ├── 安装 expo-horizon-core
│ ├── 配置配置插件(horizonAppId、面板尺寸、supportedDevices)
│ ├── 添加 quest/mobile 构建脚本
│ ├── 添加运行时设备检测(isHorizonDevice、isHorizonBuild)
│ └── 检测 expo-location / expo-notifications,然后在迁移前询问用户
│
├── 需要在 Quest 上使用定位服务?
│ └── 联网获取:expo-horizon-location README
│ ├── 用 expo-horizon-location 替换 expo-location
│ ├── 查看功能支持矩阵
│ └── 对不支持的调用进行防护(方向、地理编码、地理围栏、后台定位)
│
├── 需要在 Quest 上使用推送通知?
│ └── 联网获取:expo-horizon-notifications README
│ ├── 用 expo-horizon-notifications 替换 expo-notifications
│ ├── 在 expo-horizon-core 中配置 horizonAppId
│ ├── 使用 getDevicePushTokenAsync(不支持 Expo 推送服务)
│ └── 跳过角标计数(Quest 不支持该功能)
│
└── 需要为 Quest 构建、运行或发布应用?
└── 联网获取:expo-horizon-core README(构建变体)+ 下方的 Meta 文档
├── 构建变体:questDebug、questRelease、mobileDebug、mobileRelease
├── Meta Quest 开发者中心(设备管理、侧载)
└── Meta Horizon Store 清单要求Setup Workflow (adding Quest support to an existing Expo app)
设置流程(为现有 Expo 应用添加 Quest 支持)
Follow these steps in order when the user asks to add Meta Quest support. Do not combine steps 2 and 3 into a single install command — the sibling packages require explicit user confirmation.
-
Install and configure.
expo-horizon-core- Run .
npx expo install expo-horizon-core - Ask the user for the config plugin values before writing them. Present all options in a single prompt so the user can paste custom values or accept defaults in one pass. Show each option on its own line with its default in brackets, e.g.:
I'll add theconfig plugin to
expo-horizon-core. Please confirm or override each value (press Enter / reply "default" to accept the bracketed default):app.json- [
supportedDevices] — pipe-separated Quest devices your app supports (required for Meta Horizon Store submission).quest2|quest3|quest3s - [empty] — Meta Horizon application ID. Leave empty unless you plan to use push notifications; required by
horizonAppIdto issue device push tokens.expo-horizon-notifications - [
defaultWidth] — Default panel width. Leave blank to omit.1024dp - [
defaultHeight] — Default panel height. Leave blank to omit. If you set width/height, make sure your Expo640dpmatches (useorientationfor wide panels)."landscape" - [
disableVrHeadtracking] — Setfalseto omit thetruemanifest entry.android.hardware.vr.headtracking - [
allowBackup] — Meta recommendsfalsefor sensitive data; setfalseonly if you need Android backup in the Quest build.true
- Only write the plugin config after the user replies. Omit any option the user left blank so the package's own default applies (don't write empty strings for ,
horizonAppId, ordefaultWidth).defaultHeight - Add /
questbuild scripts tomobile.package.json - Run .
npx expo prebuild --clean - Webfetch the expo-horizon-core README for current option names and defaults before asking — the defaults above can change between releases.
- Run
-
Detect existing location / notification packages. Do NOT install the horizon equivalents yet.
- Read the project's .
package.json - Check and
dependenciesfordevDependenciesandexpo-location.expo-notifications - If neither is present, skip the rest of this workflow — the user has no migration to do.
- Read the project's
-
For each detected package, ask the user before migrating.
- If is found, ask:
expo-location"I foundin your project. Do you want me to replace it withexpo-locationso location works on Meta Quest? (Quest has no GPS, heading, geocoding, or geofencing — unsupported calls will need to be guarded withexpo-horizon-location.)"ExpoHorizon.isHorizonDevice - If is found, ask:
expo-notifications"I foundin your project. Do you want me to replace it withexpo-notificationsso push notifications work on Meta Quest? This requires aexpo-horizon-notificationsin the core config plugin, uses Meta's push service (not the Expo Push Service), and does not support badge counts orhorizonAppId."getExpoPushTokenAsync - Present the questions together if both packages are present.
- Wait for an explicit answer before running any install or edit for these packages.
- If
-
Only after the user confirms, perform the migration for the approved package(s):
- Install the horizon equivalent (or
npx expo install expo-horizon-location).expo-horizon-notifications - Uninstall the original (or
npm uninstall expo-location).expo-notifications - Update all statements to the horizon package name.
import - For notifications: ensure is set in the
horizonAppIdplugin config and addexpo-horizon-coreto the plugins array.expo-horizon-notifications - Run again.
npx expo prebuild --clean - Webfetch the relevant README (location or notifications) for the full feature support matrix and guard unsupported calls behind .
ExpoHorizon.isHorizonDevice
- Install the horizon equivalent (
-
If the user declines a migration, leave the original package untouched and note in the summary that feature X (location / notifications) will not work on thebuild until migrated.
quest
当用户要求添加 Meta Quest 支持时,请按顺序执行以下步骤。请勿将步骤 2 和 3 合并为一个安装命令——相关包需要用户明确确认。
-
安装并配置。
expo-horizon-core- 运行 。
npx expo install expo-horizon-core - 在写入配置前,请向用户确认配置插件的值。 将所有选项一次性展示给用户,以便用户可一次性粘贴自定义值或接受默认值。每个选项单独一行,并在括号中显示默认值,例如:
我将把配置插件添加到
expo-horizon-core中。请确认或修改以下每个值(按回车/回复「default」接受括号中的默认值):app.json- [
supportedDevices] — 应用支持的 Quest 设备,用竖线分隔(Meta Horizon Store 提交必填)。quest2|quest3|quest3s - [空] — Meta Horizon 应用 ID。除非计划使用推送通知,否则留空;
horizonAppId需要此 ID 来生成设备推送令牌。expo-horizon-notifications - [
defaultWidth] — 默认面板宽度。留空则不设置。1024dp - [
defaultHeight] — 默认面板高度。留空则不设置。如果设置了宽/高,请确保 Expo 的640dp与之匹配(宽面板使用orientation)。"landscape" - [
disableVrHeadtracking] — 设置为false可省略true清单条目。android.hardware.vr.headtracking - [
allowBackup] — Meta 建议对敏感数据设置为false;仅当 Quest 构建需要 Android 备份时才设置为false。true
- 仅在用户回复后写入插件配置。用户留空的选项请省略,以便使用包自身的默认值(请勿为 、
horizonAppId或defaultWidth写入空字符串)。defaultHeight - 向 中添加
package.json/quest构建脚本。mobile - 运行 。
npx expo prebuild --clean - 在询问用户前,请联网获取 expo-horizon-core README 以获取当前的选项名称和默认值——上述默认值可能会随版本更新而变化。
- 运行
-
检测现有的定位/通知包。请勿立即安装对应的 horizon 包。
- 读取项目的 。
package.json - 检查 和
dependencies中是否存在devDependencies和expo-location。expo-notifications - 如果两者都不存在,则跳过此流程的剩余部分——用户无需进行迁移。
- 读取项目的
-
对于每个检测到的包,在迁移前询问用户。
- 如果检测到 ,询问:
expo-location"我在你的项目中发现了。是否需要将其替换为expo-location以在 Meta Quest 上使用定位功能?(Quest 没有 GPS、方向传感器、地理编码或地理围栏——不支持的调用需要用expo-horizon-location进行防护。)"ExpoHorizon.isHorizonDevice - 如果检测到 ,询问:
expo-notifications"我在你的项目中发现了。是否需要将其替换为expo-notifications以在 Meta Quest 上使用推送通知?这需要在核心配置插件中设置expo-horizon-notifications,使用 Meta 的推送服务(而非 Expo 推送服务),且不支持角标计数或horizonAppId。"getExpoPushTokenAsync - 如果同时检测到两个包,请将问题一并展示。
- 在执行这些包的安装或编辑操作前,请等待用户的明确答复。
- 如果检测到
-
仅在用户确认后,对已批准的包执行迁移:
- 安装对应的 horizon 包(或
npx expo install expo-horizon-location)。expo-horizon-notifications - 卸载原包(或
npm uninstall expo-location)。expo-notifications - 将所有 语句更新为新的包名。
import - 对于通知功能:确保 插件配置中已设置
expo-horizon-core,并将horizonAppId添加到插件数组中。expo-horizon-notifications - 再次运行 。
npx expo prebuild --clean - 联网获取对应的 README(定位或通知)以查看完整的功能支持矩阵,并使用 对不支持的调用进行防护。
ExpoHorizon.isHorizonDevice
- 安装对应的 horizon 包(
-
如果用户拒绝迁移,请保留原包不变,并在总结中注明:在构建中,功能 X(定位/通知)将无法正常使用,直到完成迁移。
quest
Critical Rules
关键规则
-
Always installfirst. It is required by all other expo-horizon packages and sets up the
expo-horizon-core/questbuild flavors that other packages depend on.mobile -
Never auto-installor
expo-horizon-location. When adding Quest support, detect existingexpo-horizon-notifications/expo-locationdependencies inexpo-notificationsand ask the user whether to migrate each one. Install and configure only the packages the user explicitly approves. See the Setup Workflow above.package.json -
Usebuild variants only on Meta Quest devices. Running
questorquestDebugbuilds on standard Android phones is unsupported and will behave unexpectedly.questRelease -
Setin the config plugin. This is required for Meta Horizon Store submission. Use pipe-separated values:
supportedDevices."quest2|quest3|quest3s" -
Runafter any plugin config change. The config plugin modifies native project files at prebuild time. Stale native projects will not reflect your changes.
npx expo prebuild --clean -
Replace imports, not just packages. When migrating fromor
expo-location, update all import statements to use the new package names (expo-notifications,expo-horizon-location).expo-horizon-notifications -
Quest has no GPS, magnetic sensors, or Geocoder. Features like heading, geocoding, reverse geocoding, and geofencing are unavailable on Quest. Guard these calls withor
ExpoHorizon.isHorizonDevice.ExpoHorizon.isHorizonBuild -
Push notifications require. Without it,
horizonAppIdwill not return a valid token on Quest devices. UsegetDevicePushTokenAsync(notgetDevicePushTokenAsync) on Quest; send the returnedgetExpoPushTokenAsynctoken to your backend and deliver via Meta's push service.{ type: 'horizon', data } -
vs
isHorizonDevice. UseisHorizonBuildfor runtime hardware checks (physical Quest detection). UseisHorizonDevicefor build-time feature gating (which native code was compiled in).isHorizonBuild -
Expo Go is not supported. You must use custom development builds via.
npx expo prebuild
-
请先安装。 它是所有其他 expo-horizon 包的依赖,负责设置其他包所需的
expo-horizon-core/quest构建变体。mobile -
请勿自动安装或
expo-horizon-location。 添加 Quest 支持时,请检测expo-horizon-notifications中现有的package.json/expo-location依赖,并询问用户是否需要迁移每个包。仅安装和配置用户明确批准的包。请参阅上方的设置流程。expo-notifications -
仅在 Meta Quest 设备上使用构建变体。 在标准安卓手机上运行
quest或questDebug构建不受支持,且会出现异常行为。questRelease -
在配置插件中设置。 这是 Meta Horizon Store 提交的必填项。使用竖线分隔的值:
supportedDevices。"quest2|quest3|quest3s" -
任何插件配置更改后,请运行。 配置插件会在预构建阶段修改原生项目文件。过时的原生项目将无法反映你的更改。
npx expo prebuild --clean -
替换导入语句,而不仅仅是包。 从或
expo-location迁移时,请将所有导入语句更新为新的包名(expo-notifications、expo-horizon-location)。expo-horizon-notifications -
Quest 没有 GPS、磁力传感器或地理编码器。 方向、地理编码、逆地理编码和地理围栏等功能在 Quest 上不可用。请使用或
ExpoHorizon.isHorizonDevice对这些调用进行防护。ExpoHorizon.isHorizonBuild -
推送通知需要。 没有此 ID,
horizonAppId在 Quest 设备上无法返回有效的令牌。在 Quest 上使用getDevicePushTokenAsync(而非getDevicePushTokenAsync);将返回的getExpoPushTokenAsync令牌发送到你的后端,并通过 Meta 的推送服务进行推送。{ type: 'horizon', data } -
vs
isHorizonDevice。 使用isHorizonBuild进行运行时硬件检测(物理 Quest 设备识别)。使用isHorizonDevice进行构建时功能控制(判断编译了哪些原生代码)。isHorizonBuild -
不支持 Expo Go。 你必须通过使用自定义开发构建。
npx expo prebuild
Official References
官方参考
Always webfetch the raw markdown () if the HTML view does not render the source; the raw URL is the source of truth.
raw.githubusercontent.com/...| Topic | Official source |
|---|---|
| Repo overview and package list | expo-horizon README |
| Install, config plugin options, runtime API, native module access | expo-horizon-core README |
| Location migration, limitations, feature support matrix | expo-horizon-location README |
| Push notifications migration, token types, feature support matrix | expo-horizon-notifications README |
| Example app wiring for all three packages | expo-horizon example README |
| Panel sizing guidelines (dp values, orientation, letterboxing) | Meta Panel Sizing |
| Meta Horizon Store manifest checklist for publishing | Publish Mobile Manifest |
| Device management, casting, sideloading, ADB | Meta Quest Developer Hub |
| Server-side push delivery via Meta's push service | Horizon OS push notifications |
如果 HTML 视图无法渲染源文件,请始终联网获取原始 markdown();原始 URL 是权威来源。
raw.githubusercontent.com/...| 主题 | 官方来源 |
|---|---|
| 仓库概览和包列表 | expo-horizon README |
| 安装、配置插件选项、运行时 API、原生模块访问 | expo-horizon-core README |
| 定位迁移、限制、功能支持矩阵 | expo-horizon-location README |
| 推送通知迁移、令牌类型、功能支持矩阵 | expo-horizon-notifications README |
| 三个包的示例应用配置 | expo-horizon example README |
| 面板尺寸指南(dp 值、方向、黑边处理) | Meta Panel Sizing |
| Meta Horizon Store 发布清单检查项 | Publish Mobile Manifest |
| 设备管理、投屏、侧载、ADB | Meta Quest Developer Hub |
| 通过 Meta 推送服务实现服务端推送 | Horizon OS push notifications |