# Expo SDK Documentation
> Documentation for Expo SDK libraries, app configuration files, Expo CLI, create-expo-app, and more.
---
title: create-expo-app
description: 一个命令行工具,用于创建新的 Expo 和 React Native 项目。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/more/create-expo/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# create-expo-app
一个命令行工具,用于创建新的 Expo 和 React Native 项目。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`create-expo-app` 是一个命令行工具,用于创建和设置一个新的 Expo 和 React Native 项目。该工具通过提供多种模板来简化初始化流程,使你无需手动配置即可快速开始。
## 创建新项目
要创建新项目,请运行以下命令:
```sh
# npm
npx create-expo-app@latest --template default@sdk-55
# yarn
yarn create expo-app --template default@sdk-55
# pnpm
pnpm create expo-app --template default@sdk-55
# bun
bun create expo --template default@sdk-55
```
> **注意:** 在 SDK 55 过渡期内,不带 `--template` 标志的 `create-expo-app@latest` 会创建一个 SDK 54 项目。如果你计划在实体设备上使用 Expo Go,请使用 SDK 54 项目。否则,请使用 `--template default@sdk-55` 来创建 SDK 55 项目。
运行上述命令后,系统会提示你输入项目的应用名称。这个应用名称也会用于 app config 的 [`name`](/versions/latest/config/app#name) 属性。
```sh
你的应用名称是什么? my-app
```
## 选项
使用以下选项来自定义命令行为。
### `--yes`
使用默认选项创建新项目。
### `--no-install`
跳过安装 npm 依赖或 CocoaPods。
### `--no-agents-md`
跳过生成 **AGENTS.md**、**CLAUDE.md** 和 **.claude/settings.json**。默认情况下,`create-expo-app` 会生成这些文件,以便 AI 编码代理(例如 Claude Code)能够自动获得 Expo 特定上下文并配置 [`expo` skills 插件](https://expo.dev/expo-skills)。生成的 **AGENTS.md** 会指向与你项目 SDK 版本匹配的分版本 Expo 文档。
### `--template`
使用 [Node Package Manager](/more/create-expo#node-package-managers-support) 运行 `create-expo-app` 会使用默认模板初始化并设置一个新的 Expo 项目。
你可以使用 `--template` 选项选择以下模板之一,也可以将其作为该选项的参数传入。例如,`--template default`。
> **信息** 想要更多模板吗?请查看 [`--example`](/more/create-expo#--example) 选项,以使用展示特定功能和集成的示例应用之一来初始化你的项目。
| 模板 | 描述 |
| --- | --- |
| [`default`](https://github.com/expo/expo/tree/main/templates/expo-template-default) | 默认模板。专为构建多页面应用而设计。包含推荐工具,如 Expo CLI、已启用的 Expo Router 库和 TypeScript 配置。适用于大多数应用。 |
| [`blank`](https://github.com/expo/expo/tree/main/templates/expo-template-blank) | 安装最低必需的 npm 依赖,但不配置导航。 |
| [`blank-typescript`](https://github.com/expo/expo/tree/main/templates/expo-template-blank-typescript) | 启用 TypeScript 的空白模板。 |
| [`tabs`](https://github.com/expo/expo/tree/main/templates/expo-template-tabs) | 安装并配置基于文件的路由,启用 Expo Router 和 TypeScript。 |
| [`bare-minimum`](https://github.com/expo/expo/tree/main/templates/expo-template-bare-minimum) | 一个生成了原生目录(**android** 和 **ios**)的空白模板。会在设置过程中运行 [`npx expo prebuild`](/workflow/continuous-native-generation)。 |
### `--example`
使用此选项可以通过 [expo/examples](https://github.com/expo/examples) 中的示例来初始化项目。
例如:
- 运行 `npx create-expo-app --example with-router` 会设置一个使用 Expo Router 库的项目
- 运行 `npx create-expo-app --example with-react-navigation` 会设置一个类似默认模板的项目,但配置为使用原生的 React Navigation 库
### `--version`
打印版本号并退出。
### `--help`
打印可用选项列表并退出。
## Node Package Managers 支持
使用 `create-expo-app` 创建新项目时,也会处理为特定 Node Package Manager 所需的额外配置。
**如果你正在从一个包管理器迁移到另一个包管理器**,你需要在项目中手动完成额外配置。**如果你正在使用 [EAS](/eas)**,你也需要手动为任何额外必需步骤配置项目。
每种包管理器的所有额外步骤如下所列。
### npm
#### 本地安装
npm 是作为 Node.js 安装的一部分提供的。安装说明请参见 [Node.js 文档](https://nodejs.org/en/download/package-manager)。
#### EAS 安装
如果项目目录包含 **package-lock.json**,则默认支持。
### Yarn 1 (Classic)
#### 本地安装
Yarn 1 (Classic) 通常作为 npm 的全局依赖安装。安装说明请参见 [Yarn 1 文档](https://classic.yarnpkg.com/en/docs/getting-started)。
#### EAS 安装
如果项目目录包含 **yarn.lock**,则默认支持。
### Yarn 2+ (Modern)
#### 本地安装
安装说明请参见 [Yarn 文档](https://yarnpkg.com/getting-started/install)。
Yarn 2+ 处理包管理的方式与 Yarn 1 不同。Yarn 2+ 的核心变化之一是 [Plug'n'Play (PnP)](https://yarnpkg.com/features/pnp) 节点链接模型,而该模型无法与 React Native 配合使用。
默认情况下,使用 `create-expo-app` 和 Yarn 2+ 创建的项目会使用 [`nodeLinker`](https://yarnpkg.com/features/linkers#nodelinker-node-modules),并将其值设为 `node-modules` 来安装依赖。
```yaml
nodeLinker: node-modules
```
#### EAS 安装
EAS 上的 Yarn Modern 需要为构建启用 [Corepack](https://github.com/nodejs/corepack)。在 **eas.json** 的构建配置中将 [`corepack`](/eas/json#corepack) 设为 `true`:
```json
{
"build": {
"production": {
"corepack": true
}
}
}
```
然后,使用 [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) 字段在项目的 **package.json** 中固定 Yarn 版本。在本地运行 `yarn set version ` 会为你更新此字段:
```json
{
"packageManager": "yarn@4.14.1"
}
```
添加以上两项配置后,当 EAS 安装依赖时,Corepack 会自动下载并使用固定的 Yarn 版本。
### pnpm
#### 本地安装
需要安装 Node.js。安装说明请参见 [pnpm 文档](https://pnpm.io/installation)。
默认情况下,使用 `create-expo-app` 和 pnpm 创建的项目会使用 [`nodeLinker`](https://pnpm.io/settings#nodelinker),并将其值设为 `hoisted` 来安装依赖。
```yaml
nodeLinker: hoisted
```
> **信息** 在 **SDK 54** 及更高版本中,Expo 支持隔离安装,如果你更喜欢使用隔离依赖,可以删除 `nodeLinker` 设置。
#### EAS 安装
如果项目目录包含 **pnpm-lock.yaml**,则默认支持。
### Bun
有关使用 `bun` 创建新的 Expo 项目、从其他包管理器迁移以及在 EAS 中使用的详细信息,请参见 [Bun](/guides/using-bun) 指南。
---
---
title: Expo CLI
description: Expo CLI 是一个命令行工具,是开发者与其他 Expo 工具之间的主要接口。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/more/expo-cli/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo CLI
Expo CLI 是一个命令行工具,是开发者与其他 Expo 工具之间的主要接口。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo` 包提供了一个小巧而强大的 CLI 工具 `npx expo`,旨在帮助你在应用开发过程中保持高效推进。
## 亮点
- 为开发你的应用 [启动服务器](/more/expo-cli#develop):`npx expo start`。
- 为你的项目 [生成原生 Android 和 iOS 目录](/more/expo-cli#prebuild):`npx expo prebuild`。
- 在本地 [构建并运行](/more/expo-cli#compiling) 原生应用:`npx expo run:ios` 和 `npx expo run:android`。
- [安装和更新](/more/expo-cli#install) 与项目中 `react-native` 版本兼容的包:`npx expo install package-name`。
- `npx expo` 可以与 `npx react-native` 同时使用。
要查看 Expo CLI 中可用命令的列表,请在你的项目中运行以下命令:
```sh
npx expo -h
```
> 如果你更喜欢使用 yarn 作为包管理器,也可以运行 `yarn expo -h`。
输出应如下所示:
```sh
Usage
$ npx expo
Commands
start, export
run:ios, run:android, prebuild
install, customize, config
login, logout, whoami, register
Options
--version, -v 版本号
--help, -h 使用信息
```
你可以使用 `--help` 或 `-h` 标志运行任何命令来了解更多信息:
```sh
npx expo login -h
```
## 安装
Expo CLI 包含在 `expo` 包中。你可以使用 npm 或 yarn 安装它:
```sh
yarn add expo
```
> 未使用 [Expo Prebuild](/more/expo-cli#prebuild) 的项目(也称为 _Bare 项目_)需要进行额外设置,以确保所有自定义 Expo 打包功能正常工作:[Metro:Bare 工作流设置](/versions/latest/config/metro#bare-workflow-setup)。
## 开发
通过运行以下命令启动开发服务器来处理你的项目:
```sh
npx expo start
```
> 你也可以将 `npx expo` 作为 `npx expo start` 的别名来运行。
此命令会在 `http://localhost:8081` 上启动一个服务器,客户端可以通过它与打包器交互。默认的打包器是 [Metro](https://metrobundler.dev/)。
进程中显示的 UI 被称为 **终端 UI**。它包含一个二维码(用于开发服务器 URL)以及你可以按下的一组键盘快捷键:
| 键盘快捷键 | 描述 |
| --- | --- |
| A | 在已连接的 Android 设备上打开项目。 |
| Shift + A | 选择一个 Android 设备或模拟器来打开。 |
| I | 在 iOS 模拟器中打开项目。 |
| Shift + I | 选择一个 iOS 模拟器来打开。 |
| W | 在网页浏览器中打开项目。这可能需要在你的项目中安装 webpack。 |
| R | 在任何已连接设备上重新加载应用。 |
| S | 在 Expo Go 和开发构建之间切换启动目标。 |
| M | 在任何已连接的原生设备上打开开发菜单(不支持 web)。 |
| Shift + M | 选择更多要在已连接设备上触发的命令。这包括切换性能监视器、打开元素检查器、重新加载设备以及打开开发菜单。 |
| J | 为任何已连接且使用 Hermes 作为 JavaScript 引擎的设备打开 React Native DevTools。[了解更多](/guides/using-hermes#javascript-inspector-for-hermes)。 |
| O | 在编辑器中打开项目代码。这可以通过 `EXPO_EDITOR` 和 `EDITOR` [环境变量](/more/expo-cli#environment-variables)进行配置。 |
| E | 在终端中将开发服务器 URL 显示为二维码。 |
| ? | 显示所有终端 UI 命令。 |
### 启动目标
如果项目中安装了 `expo-dev-client`,`npx expo start` 命令会自动在开发构建中启动应用。否则,它会在 Expo Go 中启动应用。
或者,你也可以通过向命令传递以下标志来强制指定启动目标:
- `--dev-client`:始终以开发构建启动应用。
- `--go`:始终在 Expo Go 中启动应用。
你还可以在运行时通过在 **终端 UI** 中按下 S 来切换启动目标。默认情况下,`run` 命令在编译开发构建后也会使用 `--dev-client`。
### 服务器 URL
默认情况下,项目通过局域网连接提供服务。你可以通过使用 `npx expo start --localhost` 标志将此行为更改为仅使用 localhost。
其他可用选项包括:
- `--port`:启动开发服务器所使用的端口(不适用于 webpack 或 [隧道 URL](/more/expo-cli#tunneling))。使用 `--port 0` 可自动使用第一个可用端口。默认值:**8081**。
- `--https`:**(已弃用,推荐使用 `--tunnel`)** 使用安全来源启动开发服务器。目前仅支持 web。
你可以通过 `EXPO_PACKAGER_PROXY_URL` 环境变量强制将 URL 设置为任意值。例如:
```sh
export EXPO_PACKAGER_PROXY_URL=http://expo.dev
npx expo start
```
将会打开应用到:`exp://expo.dev:80`(`:80` 是针对 Android WebSockets 的临时解决方法)。
#### 隧道
受限的网络条件(公共 Wi-Fi 中很常见)、防火墙(Windows 用户中很常见)或模拟器配置错误,都会使远程设备难以通过 lan/localhost 连接到你的开发服务器。
有时,通过一个任何设备在有互联网连接时都可访问的代理 URL 连接开发服务器会更容易,这被称为 **隧道**。`npx expo start` 通过 [ngrok](https://ngrok.com) 提供了对 **隧道** 的内置支持。
要启用隧道,首先安装 `@expo/ngrok`:
```sh
npm i -g @expo/ngrok
```
然后运行以下命令,通过一个 _隧道_ URL 启动你的开发服务器:
```sh
npx expo start --tunnel
```
这将通过如下公共 URL 提供你的应用:`https://xxxxxxx.bacon.19000.exp.direct:80`。
使用 `EXPO_TUNNEL_SUBDOMAIN` 环境变量可以实验性地设置隧道 URL 的子域名。这对于在 iOS 上测试通用链接很有用。这可能会导致 `expo-linking` 和 Expo Go 出现意外问题。通过传递一个 `string` 值来选择要使用的精确子域名,该值不能是以下之一:`true`、`false`、`1`、`0`。
**缺点**
- 隧道比本地连接更慢,因为请求必须被转发到公共 URL。
- 隧道 URL 是公开的,任何有网络连接的设备都可以访问。Expo CLI 通过在 URL 开头添加随机性来降低暴露风险。你可以通过清空项目中的 **.expo** 目录来重置随机性。
- 隧道要求两台设备都具备网络连接,这意味着该功能不能与 `--offline` 标志一起使用。
隧道依赖第三方托管服务,这意味着它有时可能会遇到间歇性问题,例如 `ngrok tunnel took too long to connect` 或 `Tunnel connection has been closed. This is often related to intermittent connection problems with the Ngrok servers...`。在报告问题之前,请务必先检查 [Ngrok 服务状态](https://status.ngrok.com/)。一些 Windows 用户还报告称,需要修改他们的杀毒软件设置,以允许 Ngrok 正常工作。
#### 离线
你可以使用 `--offline` 标志在没有网络连接的情况下开发:
```sh
npx expo start --offline
```
离线模式会阻止 CLI 发出网络请求。如果你不使用该标志且你的电脑没有互联网连接,则会自动启用离线支持,只是验证连通性会多花一点时间。
Expo CLI 会发出网络请求,使用你的用户凭据对 manifest 进行签名,以确保敏感信息在 Expo Go 这类可复用运行时中处于沙箱隔离状态。
### .expo 目录
当你第一次在项目中启动开发服务器时,项目根目录下会创建一个 **.expo** 目录。它包含两个文件:
- **devices.json**:包含最近打开过该项目的设备信息。
- **settings.json**:包含用于提供项目 manifest 的服务器配置信息。
这两个文件都包含与你本地电脑相关的信息。这就是为什么在创建新项目时,默认情况下 **.expo** 目录会被包含到 **.gitignore** 文件中的原因。它并不打算与其他开发者共享。
## 构建
一个 React Native 应用由两部分组成:一个原生运行时([编译](/more/expo-cli#compiling)),以及静态文件,例如 JavaScript bundle 和资源文件([导出](/more/expo-cli#exporting))。Expo CLI 提供了执行这两项任务的命令。
### 编译
你可以使用 `run` 命令在本地编译你的应用:
```sh
npx expo run:ios
npx expo run:android
```
**亮点**
- 使用 `--device` 标志可直接在已连接设备上构建,不会产生全局副作用。支持锁定设备,让你可以立即重试,而不必重新构建。
- 可通过 CLI 自动为开发环境对 iOS 应用进行代码签名,无需打开 Xcode。
- 智能日志解析会显示来自项目源代码的警告和错误,不像 Xcode 那样会显示来自 node_modules 的数百条无害警告。
- 导致应用崩溃的致命错误会直接显示在终端中,从而无需在 Xcode 中复现。
`npx expo run:ios` 只能在 Mac 上运行,并且必须安装 Xcode。你可以使用 `eas build -p ios` 从任何电脑在云端构建应用。同样,`npx expo run:android` 需要你的电脑上安装并配置好 Android Studio 和 Java。
在本地构建对于开发原生模块和[调试复杂的原生问题](/debugging/runtime-issues#native-debugging)很有用。由于预先配置好的云环境,使用 `eas build` 进行远程构建是一个更稳健的选择。
如果你的项目没有对应的原生目录,`npx expo prebuild` 命令会先运行一次,在构建之前生成相应的目录。
例如,如果你的项目根目录下没有 **ios** 目录,那么 `npx expo run:ios` 会先运行 `npx expo prebuild -p ios`,然后再编译你的应用。有关此过程的更多信息,请参见 [Expo Prebuild](/workflow/continuous-native-generation)。
**跨平台参数**
- `--no-build-cache`: 在构建前清除原生缓存。在 iOS 上,这指的是 **derived data** 目录。清除缓存有助于分析构建耗时。
- `--no-install`: 跳过安装依赖。在 iOS 上,如果项目 `package.json` 中的 `dependencies` 字段发生变化,这也会跳过运行 `npx pod-install`。
- `--no-bundler`: 跳过启动开发服务器。如果开发服务器已经通过其他进程在提供应用,则会自动启用。
- `-d, --device [device]`: 要在哪个设备名称或 ID 上构建应用。你可以在不带参数的情况下使用 `--device`,从可用选项列表中选择一个设备。它支持已连接设备和虚拟设备。使用 `--device generic` 可在不针对特定设备的情况下构建(仅构建工作流)。
- `-o, --output `: 构建完成后,将生成的应用二进制文件复制到的目录。适用于 CI/CD 流水线,或当你希望二进制文件位于可预测位置时。
- `-p, --port `: 启动开发服务器的端口。**默认:8081**。这仅与开发构建相关。生产构建会先[导出](/more/expo-cli#exporting)项目,并在安装到设备前将文件嵌入原生二进制中。
- `--binary `: 要安装到设备上的二进制文件路径。提供此参数后,将跳过构建过程并尝试直接安装二进制文件。如果该二进制文件不是为正确设备构建的,例如它是为模拟器构建的或已安装到设备上,则命令会失败。
#### 编译 Android
Android 应用可以有多个不同的 **变体**,它们在项目的 `build.gradle` 文件中定义。可以使用 `--variant` 标志选择变体:
##### `debug` 变体
使用 `debug` 变体进行调试构建:
```sh
npx expo run:android --variant debug
```
##### `debugOptimized` 变体
> **重要** `debugOptimized` 从 SDK 54 开始可用。
使用 `debugOptimized` 变体可以获得更快的开发体验,同时性能接近发布构建,并保持整体构建处于便于调试的模式:
```sh
npx expo run:android --variant debugOptimized
```
使用此变体时,请注意以下几点:
- 如同发布构建一样优化 C++ 库,提升运行时性能
- 在 EAS Build 中,使用匹配的 Gradle 命令,例如 [`eas.json` 中的 `:app:assembleDebugOptimized`](/build-reference/apk#configuring-a-profile-to-build-apks)
- **限制**:C++ 调试已禁用,C++ 崩溃可能具有可读性较差的堆栈跟踪
##### `release` 变体
你可以通过运行以下命令为生产环境编译 Android 应用:
```sh
npx expo run:android --variant release
```
此构建不会自动进行代码签名,因此不能直接提交到 Google Play 商店。此命令应用于测试只会在生产构建中出现的 bug。要生成可为 Play 商店进行代码签名的生产构建,我们建议使用 [EAS Build](/build/introduction)。
##### 调试原生 Android 项目
你可以通过在 Android Studio 中打开 **android** 目录,使用原生调试工具调试原生 Android 项目:
```sh
open -a /Applications/Android Studio.app android
```
如果你使用自定义的 Android 项目并配置了不同的 product flavor,你可以使用 `--variant` 和 `--app-id` 标志同时配置 flavor 和应用 ID:
```sh
npx expo run:android --variant freeDebug --app-id dev.expo.myapp.free
```
有关更多信息,请参见[使用 Android product flavors 进行本地构建](/guides/local-app-development#local-builds-using-android-product-flavors)指南。
#### 编译 iOS
iOS 应用可以有多个 **scheme**,用于表示不同的子应用,例如 App Clip、watchOS 应用、Safari 扩展等。默认情况下,`npx expo run:ios` 会为你的 iOS 应用选择 scheme。你可以使用 `--scheme ` 参数选择自定义 scheme。如果你只传入 `--scheme` 参数,Expo CLI 会提示你从 Xcode 项目中可用的选项列表里选择一个 scheme。
你选择的 scheme 会过滤掉在选择提示中显示的 `--device` 选项,例如,选择 Apple TV scheme 时只会显示可用的 Apple TV 设备。
你可以通过运行以下命令为生产环境编译 iOS 应用:
```sh
npx expo run:ios --configuration Release
```
此构建不会自动进行代码签名,因此不能直接提交到 Apple App Store。`npx expo run:ios` 主要应用于测试只会在生产构建中出现的 bug。原生代码签名需要进行多次网络请求,并且容易受到 Apple 服务器上多种不同类型错误的影响。要生成可为 App Store 进行代码签名的生产构建,我们建议使用 [EAS Build](/build/introduction)。
当你将应用编译到模拟器上时,模拟器的原生日志会通过管道传输到终端中的 Expo CLI 进程。这对于快速查看可能导致致命错误的 bug 很有用,例如缺少权限的消息。物理 iOS 设备不支持错误输出管道传输。
你可以通过在 Xcode 中打开项目并从 Xcode 重新构建,使用 `lldb` 和所有 Apple 原生调试工具进行调试:
```sh
xed ios
```
从 Xcode 构建很有用,因为你可以设置原生断点并分析应用的任何部分。请务必在源代码管理(git)中跟踪更改,以防你需要使用 `npx expo prebuild -p ios --clean` 重新生成原生应用。
##### 仅构建工作流
你可以使用 `generic` 设备选项,在不针对特定设备的情况下构建 iOS 模拟器应用:
```sh
npx expo run:ios --device generic
```
上述命令使用通用的 Xcode 目标(`generic/platform=iOS Simulator`),而不是特定的模拟器 UDID,这对于以下场景很有用:
- **CI/CD 流水线**:在构建机上无需配置模拟器即可构建模拟器应用。
- **分发模拟器构建**:创建可共享并可在任何兼容模拟器上运行的 **.app** 包。
- **仅构建工作流**:当你只需要编译后的二进制文件,而不需要安装或启动时。
构建完成后,CLI 会输出生成的 **.app** 包路径:
```sh
✓ 构建完成
Binary: ~/Library/Developer/Xcode/DerivedData/.../Release-iphonesimulator/MyApp.app
```
你可以将其与 `--configuration Release` 组合,创建生产模拟器构建,并使用 `--output` 将二进制文件复制到指定目录:
```sh
npx expo run:ios --configuration Release --device generic --output ./build
```
上述命令会将生成的 **.app** 包复制到 **./build/MyApp.app**。
**iOS 开发签名**
如果你想看看应用在设备上的运行方式,只需连接设备,运行 `npx expo run:ios --device`,然后选择你已连接的设备即可。
Expo CLI 会自动为开发环境对设备进行签名、安装应用并启动它。
如果你的电脑上没有设置任何开发者配置文件,那么你需要按照此指南在 Expo CLI 之外手动设置它们:[设置 Xcode 签名](https://expo.fyi/setup-xcode-signing)。
### 导出
你可以通过运行以下命令,使用 Metro bundler 导出应用的 JavaScript 和资源文件:
```sh
npx expo export
```
在使用 `eas update` 或编译原生运行时时,这会自动完成。`export` 命令的工作方式与大多数 Web 框架类似:
- bundler 会将应用代码转译并打包到 **生产** 环境中,剥离所有受 `__DEV__` 布尔值保护的代码。
- 所有静态文件都会被复制到静态 **dist** 目录中,可由静态主机提供服务。
- **public** 目录中的内容会按原样复制到 **dist** 目录中。
提供以下选项:
- `--platform `: 选择要编译的平台:'ios'、'android'、'all'。**默认:all**。如果在 app 配置中进行了设置,也可以使用 'web'。更多信息请参见 [自定义 Metro](/guides/customizing-metro)。
- `--dev`: 为 **开发** 环境打包,不进行代码压缩,也不剥离 `__DEV__` 布尔值。
- `--output-dir `: 导出静态文件的目录。**默认:dist**
- `--max-workers `: 允许 bundler 创建的最大任务数。将其设置为 `0` 会在同一进程中执行所有转译,这意味着你可以轻松调试 Babel 转译。
- `-c, --clear`: 在导出前清除 bundler 缓存。
- `--no-minify`: 跳过 JavaScript 和 CSS 资源的压缩。
- `--no-bytecode`: 跳过为原生平台生成 Hermes 字节码。仅在分析 bundle 大小时使用,切勿将 UTF-8 bundle 直接发布到原生平台,因为这会导致启动时间大幅延长。
- `--no-ssg`: 跳过为 Web 路由导出静态 HTML 文件。此选项仅在 **dist** 目录中生成服务器代码。适用于 [API 路由](/router/web/api-routes)。
#### 使用子路径托管
> **重要** [实验性](/more/release-statuses#experimental) 功能。
你可以通过在 [app 配置](/workflow/configuration) 中设置 `experiments.baseUrl` 字段来配置静态资源前缀:
```json
{
"expo": {
"experiments": {
"baseUrl": "/my-root"
}
}
}
```
这将导出一个所有资源都以前缀 `/my-root` 发布的网站。例如,位于 `assets/image.png` 的图片将预期托管在 **/my-root/assets/image.png**。实际文件将位于与服务器上预期托管在 `/my-root` 的整个目录相同的文件系统位置。
Expo Router 对 `baseUrl` 提供了内置支持。当使用 `Link` 和 `router` API 时,`baseUrl` 会自动添加到 URL 前面。
```jsx
import { Link } from 'expo-router';
export default function Blog() {
return 前往博客文章;
}
```
这将 **导出** 为以下内容:
```html
前往博客文章
```
如果你直接使用 ``、React Navigation 或 `Linking` API,则需要手动在前面添加 `baseUrl`。
`baseUrl` 功能仅用于生产环境,且必须在导出网站之前设置。如果你更改了该值,必须重新导出网站。
如果你通过 `require` 或 `import` 引用图片和其他资源,它们会自动工作。如果你直接引用资源 URL,则需要手动追加 **baseUrl**。
```jsx
import { Image } from 'expo-image';
export default function Blog() {
return ;
}
```
这将 **导出** 为以下内容:
```html
```
如果手动传入 URL,则需要手动添加前缀:
```jsx
export default function Blog() {
return ;
}
```
### 使用 webpack 导出
> **警告** **[已弃用](/more/release-statuses#deprecated)**:从 SDK 50 开始,Expo Webpack 已被弃用,建议改用通用 Metro(`npx expo export`)。更多信息请参见[从 Webpack 迁移到 Expo Router](/router/migrate/from-expo-webpack)。
你可以通过运行以下命令,使用 webpack 导出 Web 应用的 JavaScript 和资源文件:
```sh
npx expo export:web
```
- `--dev`: 以 'development' 模式打包,不进行代码压缩,也不剥离 `__DEV__` 布尔值。
- `-c, --clear`: 在导出前清除 bundler 缓存。
如果你的项目在 `app.json` 中通过 `expo.web.bundler: 'metro'` 字段配置为使用 `metro` 打包 Web 项目,则此命令将被禁用。
## 预构建
```sh
npx expo prebuild
```
在原生应用可以编译之前,必须先生成原生源代码。Expo CLI 提供了一个名为 _prebuild_ 的独特而强大的系统,它会为你的项目生成原生代码。要了解更多,请阅读 [Expo Prebuild 文档](/workflow/continuous-native-generation)。
## 代码检查
```sh
npx expo lint
```
代码检查有助于强制执行最佳实践,并确保你的代码保持一致。`npx expo lint` 命令会使用 Expo 特定设置来配置 ESLint,并运行针对 Expo 框架优化过选项的 `npx eslint` 命令。通过运行 `npx expo lint --fix`,代码检查问题可以自动修复。
默认情况下,运行 `npx expo lint` 会针对 **src**、**app** 和 **components** 目录中的所有文件。你也可以将自定义文件或目录作为参数传递给 lint 命令。例如:
```sh
npx expo lint ./utils constants.ts
```
默认情况下,所有匹配 `.js, .jsx, .ts, .tsx, .mjs, .cjs` 扩展名的文件都会被检查。你可以通过传递 `--ext` 标志来自定义扩展名。例如,要只检查 `.ts` 和 `.tsx` 文件,你可以使用 `--ext` 选项:`npx expo lint --ext .ts,.tsx` 或 `npx expo lint --ext .js --tsx .tsx`。
如果你需要更多自定义,可以使用 `--` 运算符传递额外参数。例如,要向 ESLint 传递 `--no-error-on-unmatched-pattern` 标志,可以运行:
```sh
npx expo lint -- --no-error-on-unmatched-pattern
```
如果你需要更多自定义,可以直接使用 `npx eslint`。
[使用 ESLint](/guides/using-eslint) — 了解更多关于在 Expo 项目中使用 ESLint 确保最佳实践的信息。
## 配置
通过运行以下命令评估应用配置(**app.json**,或 **app.config.js**):
```sh
npx expo config
```
- `--full`:包含所有项目配置数据。
- `--json`:以 JSON 格式输出,这对于将 **app.config.js** 转换为 **app.config.json** 很有用。
- `-t, --type`:[要显示的配置类型](/more/expo-cli#config-type)。
### 配置类型
从应用配置中会生成三种不同的配置类型:
- `public`:与 OTA 更新一起使用的清单文件。可以把它想象成原生应用中的 `index.html` 文件的 `` 元素。
- `prebuild`:由 [Expo Prebuild](/workflow/continuous-native-generation) 使用的配置,包括异步修饰器。这是配置不可序列化的唯一时机。
- `introspect`:`prebuild` 配置的一个子集,只显示内存中的修改,例如 `Info.plist` 或 **AndroidManifest.xml** 的更改。了解更多关于 [introspection](/config-plugins/development-and-debugging#introspection)。
## 安装
与 Web 不同,React Native 不向后兼容。这意味着 npm 包通常需要与你项目中当前安装的 `react-native` 副本完全匹配正确的版本。Expo CLI 提供了一个尽力而为的工具,通过使用常用包列表和已知可用的版本组合来完成这项工作。只需使用 `install` 命令,就可以直接替代 `npm install`:
```sh
npx expo install expo-camera
```
运行该命令的单个实例时,你也可以安装多个包:
```sh
npx expo install typescript expo-sms
```
你可以使用 `--` 运算符直接向底层包管理器传递参数:
```sh
yarn expo install typescript -- -D
```
### 版本验证
你可以使用 `--check` 和 `--fix` 标志进行验证和修正:
- `--check`:检查哪些已安装包需要更新。
- `--fix`:自动更新任何无效的包版本。
示例:
```sh
npx expo install --check
```
`npx expo install --check` 会提示你哪些已安装包的安装不正确。它还会提示是否将这些包在本地安装为兼容版本。在持续集成(CI)中,它会以非零状态退出。这意味着你可以用它来进行持续的不可变验证。相较之下,`npx expo install --fix` 会在需要时始终修复包,不受环境影响。
你可以通过传入特定包来验证它们:
```sh
npx expo install react-native expo-sms --check
```
命令 `npx expo install expo-camera` 和 `npx expo install expo-camera --fix` 目的相同,`--fix` 命令适合用于升级项目中的所有包,例如:
```sh
npx expo install --fix
```
### 配置依赖验证
在某些情况下,你可能想使用一个不同于 `npx expo install` 所推荐版本的包版本。在这种情况下,你可以通过在项目的 **package.json** 中使用 [`expo.install.exclude`](/versions/latest/config/package-json#exclude) 属性,将特定包从版本检查中排除。
### 安装包管理器
`npx expo install` 支持 `bun`、`npm`、`pnpm` 和 `yarn`。
你可以使用命名参数强制指定包管理器:
- `--bun`:使用 `bun` 安装依赖。若存在 **bun.lockb** 或 **bun.lock**,则为默认值。
- `--npm`:使用 `npm` 安装依赖。若存在 **package-lock.json**,则为默认值。
- `--pnpm`:使用 `pnpm` 安装依赖。若存在 **pnpm-lock.yaml**,则为默认值。
- `--yarn`:使用 `yarn` 安装依赖。若存在 **yarn.lock**,则为默认值。
## 身份验证
Expo CLI 提供可与 `npx expo start` 命令配合使用的身份验证方法。身份验证用于对清单进行“代码签名”,以便安全地使用 OTA。可以把它理解为 Web 上的 HTTPS。
1. 使用 `npx expo register` 注册账户。
2. 使用 `npx expo login` 登录你的账户。
3. 使用 `npx expo whoami` 查看当前已认证的是哪个账户。
4. 使用 `npx expo logout` 退出登录。
这些凭据在 Expo CLI 和 EAS CLI 之间共享。
## 自定义
有时你可能希望自定义一个原本会由 Expo CLI 在内存中生成的项目文件。当使用 Expo CLI 之外的工具时,你需要保留默认配置文件,否则你的应用可能无法按预期运行。你可以通过运行以下命令生成文件:
```sh
npx expo customize
```
从这里,你可以选择生成如下基础项目文件:
- **babel.config.js** -- Babel 配置。如果你计划使用 Expo CLI 之外的工具来打包项目,则必须存在此文件。
- **webpack.config.js** -- 用于 Web 开发的默认 webpack 配置。
- **metro.config.js** -- 用于通用开发的默认 Metro 配置。`npx react-native` 需要使用它。
- **tsconfig.json** -- 创建一个 TypeScript 配置文件并安装所需依赖。
## 环境变量
| 名称 | 类型 | 描述 |
| --- | --- | --- |
| `HTTP_PROXY` | **string** | 用于连接所有网络请求的 HTTP/HTTPS 代理 URL。配置 [Undici EnvHttpProxyAgent](https://github.com/nodejs/undici/blob/main/docs/docs/api/EnvHttpProxyAgent.md)。 |
| `EXPO_NO_WEB_SETUP` | **boolean** | 阻止 CLI 在使用 Web 功能之前强制安装 Web 依赖(`react-dom`、`react-native-web`、`@expo/webpack-config`)。这对于你希望进行非标准 Web 开发的情况很有用。 |
| `EXPO_OFFLINE` | **boolean** | 在适用时跳过所有网络请求。这在网络连接较差的环境中可加快开发速度。 |
| `EXPO_NO_TYPESCRIPT_SETUP` | **boolean** | 阻止 CLI 在 `npx expo start` 时强制配置 TypeScript。更多信息请参阅 [TypeScript 指南](/guides/typescript)。 |
| `DEBUG=expo:*` | **string** | 为 CLI 启用调试日志,你可以使用 [`debug` 约定](https://github.com/debug-js/debug#conventions) 来配置它。 |
| `EXPO_DEBUG` | **boolean** | `DEBUG=expo:*` 的别名。 |
| `EXPO_PROFILE` | **boolean** | 为 CLI 启用性能分析统计信息,这不会对你的应用进行性能分析。 |
| `EXPO_NO_CACHE` | **boolean** | 禁用所有全局缓存。默认情况下,应用配置 JSON schema、用于模拟器和仿真器的 Expo Go 二进制文件,以及项目模板都会缓存在你机器上的全局 **.expo** 目录中。 |
| `CI` | **boolean** | 启用后,CLI 将禁用交互功能,跳过可选提示,并在非可选提示上失败。示例:如果任何已安装包已过期,`CI=1 npx expo install --check` 将失败。 |
| `EXPO_NO_TELEMETRY` | **boolean** | 禁用匿名使用情况收集。[了解更多关于遥测的信息](/more/expo-cli#telemetry)。 |
| `EXPO_NO_GIT_STATUS` | **boolean** | 在诸如 `npx expo prebuild --clean` 之类可能有风险的操作期间,跳过关于 git 状态的警告。 |
| `EXPO_NO_REDIRECT_PAGE` | **boolean** | 禁用用于选择应用的重定向页面。该页面会在用户安装了 `expo-dev-client` 时显示,并且使用 `npx expo start` 而不是 `npx expo start --dev-client` 启动项目。 |
| `EXPO_PUBLIC_FOLDER` | **string** | 与 Metro 一起用于 Web 的公共目录路径。[了解更多关于自定义 Metro 的信息](/guides/customizing-metro)。默认值:`public` |
| `EDITOR` | **string** | 在终端 UI 中按下 O 时要打开的编辑器名称。此值会被许多命令行工具使用。 |
| `EXPO_EDITOR` | **string** | Expo 专用版本的 `EDITOR` 变量,在定义时具有更高优先级。 |
| `EXPO_IMAGE_UTILS_NO_SHARP` | **boolean** | 禁用全局 Sharp CLI 安装的使用,改用更慢的 Jimp 包进行图像处理。这用于诸如 `npx expo prebuild` 生成应用图标的场景。 |
| `EXPO_TUNNEL_SUBDOMAIN` | **boolean** | , Experimental禁用将 `exp.direct` 作为 `--tunnel` 连接的主机名。这启用 **https://** 转发,可用于在 iOS 上测试通用链接。这可能会导致 `expo-linking` 和 Expo Go 出现意外问题。通过传递一个不属于以下值的 `string` 值来选择要使用的精确子域:`true`、`false`、`1`、`0`。 |
| `EXPO_METRO_NO_MAIN_FIELD_OVERRIDE` | **boolean** | 强制 Expo CLI 对所有平台使用项目 **metro.config.js** 中的 [`resolver.resolverMainFields`](https://metrobundler.dev/docs/configuration/#resolvermainfields)。默认情况下,Expo CLI 会对 Web 使用 `['browser', 'module', 'main']`(这是 webpack 的默认值),而对其他平台使用用户定义的 main fields。 |
| ~`EXPO_NO_INSPECTOR_PROXY`~ | **boolean** | , Deprecated禁用经过定制、并增强支持 Chrome DevTools 协议的 inspector proxy。这包括对网络 inspector 的支持。 |
| `EXPO_NO_CLIENT_ENV_VARS` | **boolean** | 防止将 `EXPO_PUBLIC_` 环境变量内联到客户端 bundle 中。 |
| `EXPO_NO_DOTENV` | **boolean** | 阻止 Expo CLI 加载所有 `.env` 文件。 |
| `EXPO_NO_METRO_LAZY` | **boolean** | 阻止向 Metro URL 添加 `lazy=true` 查询参数(`metro@0.76.3` 及更高版本)。这会禁用 `import()` 支持。 |
| `EXPO_USE_TYPED_ROUTES` | **boolean** | 使用 `expo.experiments.typedRoutes` 在 Expo Router 中启用静态类型路由。 |
| ~`EXPO_METRO_UNSTABLE_ERRORS`~ | **boolean** | , Deprecated禁用 Metro 打包错误的反向依赖堆栈跟踪。默认启用。 |
| ~`EXPO_USE_METRO_WORKSPACE_ROOT`~ | **boolean** | , Deprecated: SDK 52+启用 Metro 的自动服务器根目录检测。这会将服务器根目录更改为工作区根目录。适用于 monorepo。 |
| `EXPO_NO_METRO_WORKSPACE_ROOT` | **boolean** | , SDK 52+禁用 Metro 的自动服务器根目录检测。禁用后不会将服务器根目录更改为工作区根目录。启用它对 monorepo 很有用。 |
| ~`EXPO_USE_UNSTABLE_DEBUGGER`~ | **boolean** | , Deprecated: SDK 52+启用 React Native 的实验性调试器。 |
| `EXPO_ADB_USER` | **string** | 设置应与 ADB 命令中的 `--user` 一起传递的 `user` 编号。用于在具有多个配置文件的 Android 设备上安装 APK。默认值为 `0`。 |
| `EXPO_NO_TELEMETRY_DETACH` | **boolean** | , SDK 51+在 `@expo/cli` 的主线程中发送遥测事件。这会导致 CLI 变慢,因为它需要等待所有事件发送完成。 |
| `EXPO_UNSTABLE_ATLAS` | **boolean** | , Experimental, SDK 51+在开发或导出期间收集 Metro bundle 信息。从 SDK 53 开始,此环境变量已弃用,改用 `EXPO_ATLAS`。 |
| `EXPO_ATLAS` | **boolean** | , SDK 53+在开发或导出期间收集 Metro bundle 信息。 |
| `EXPO_NO_BUNDLE_SPLITTING` | **boolean** | , Experimental, SDK 51+在生产环境中禁用 Metro 在异步导入时拆分 chunk(仅限 web)。 |
| `EXPO_USE_METRO_REQUIRE` | **boolean** | , SDK 52+启用 Expo 自定义的 Metro `require` 实现和基于 `string` 的模块 ID。这可以为 React Server Components 带来更好的调试体验和确定性的 ID。不支持旧版 RAM bundles。 |
| `EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH` | **boolean** | , Experimental, SDK 52+启用急切打包模式,其中转换会在整个 bundle 创建完成后以未缓存方式运行。这是生产环境 tree shaking 所必需的,但对开发环境打包的优化较少。 |
| `EXPO_UNSTABLE_TREE_SHAKING` | **boolean** | , Experimental, SDK 52+在所有平台上启用不稳定的 tree shaking 支持。更多细节请参阅 [tree shaking](/guides/tree-shaking)。 |
| `EXPO_NO_REACT_NATIVE_WEB` | **boolean** | , Deprecated: SDK 56+启用实验模式,在该模式下 Web 上运行 Expo 应用不需要 React Native Web。 |
| `EXPO_NO_DEPENDENCY_VALIDATION` | **boolean** | , SDK 52+通过 `npx expo install` 和 `npx expo start` 安装包时,禁用内置依赖验证。 |
| `EXPO_WEB_DEV_HYDRATE` | **boolean** | 为 Web 项目在开发环境中启用 React hydration。这可以帮助你尽早发现 hydration 问题。 |
| `EXPO_UNSTABLE_LIVE_BINDINGS` | **boolean** | , Experimental, SDK 54+在实验性的 import/export 支持中禁用 live binding。默认启用。live binding 可以改善循环依赖支持,但可能会导致性能略差。 |
| `EXPO_UNSTABLE_LOG_BOX` | **boolean** | , Experimental, SDK 55+为原生应用启用实验性的 LogBox 错误覆盖层。Web 默认启用。 |
| `EXPO_NO_QR_CODE` | **boolean** | 阻止 CLI 在控制台显示二维码。 |
## 遥测
Expo 开发工具会收集有关常规使用情况的匿名数据。这有助于我们了解某个功能何时未按预期工作。遥测是完全可选的,你可以通过使用 `EXPO_NO_TELEMETRY=1` 环境变量来选择退出。
---
---
title: 术语表
description: 文档中使用的非显而易见术语列表,涉及 Expo 或更广泛的跨平台开发。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/more/glossary-of-terms/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# 术语表
文档中使用的非显而易见术语列表,涉及 Expo 或更广泛的跨平台开发。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
### Android
由 Google 赞助、供 **Android** 设备使用的移动操作系统。
### App config
位于项目根目录中名为 **app.json**、**app.config.json**、**app.config.js** 或 **app.config.ts** 的文件。有关更多信息,请参阅 [app config 配置](/workflow/configuration)。
此文件用于以下目的:
- 配置 [Expo CLI](/more/glossary-of-terms#expo-cli) 的工作方式。
- 在 EAS Update 中生成项目的公开 [manifest](/more/glossary-of-terms#manifest)(可把它理解为原生应用里的 **index.html**)。
- 列出会影响 `npx expo prebuild` 如何生成原生代码的 Expo [config plugins](/more/glossary-of-terms#config-plugin)。
### app.json
一个 [app config](/more/glossary-of-terms#app-config) 文件。
### Apple capabilities
由 Apple 提供的云服务。应用必须在 [Apple Developer Portal](/more/glossary-of-terms#apple-developer-portal) 中启用这些服务。
### Apple Developer Portal
Apple 用于管理应用代码签名的[官方网站](https://developer.apple.com/)。EAS Credentials 会自动处理开发者在开发应用时可能需要访问该网站的许多常见原因。
### Auto capability signing
EAS Build 的一项功能,可根据项目的 entitlements 文件自动启用或禁用 [Apple capabilities](/more/glossary-of-terms#apple-capabilities)。[了解更多](/build-reference/ios-capabilities)。
### Autolinking
一种跨平台工具,用于通过原生包管理器自动将原生模块链接到原生应用。
- 在 Android 上,该工具用于 **android/app/build.gradle**,并在 [Gradle](/more/glossary-of-terms#gradle) 同步过程中调用。
- 在 iOS 上,该工具用于 [CocoaPods](/more/glossary-of-terms#cocoapods) 的 **ios/Podfile**,并在执行 `pod install` 时调用。
Autolinking 有两个版本:[Expo Autolinking](/more/glossary-of-terms#expo-autolinking) 和 [Community Autolinking](/more/glossary-of-terms#community-autolinking)。
默认的 [Prebuild template](/more/glossary-of-terms#prebuild-template) 包含对 [Expo Autolinking](/more/glossary-of-terms#expo-autolinking) 和 [Community Autolinking](/more/glossary-of-terms#community-autolinking) 分支的支持。
### Babel
用于移除运行时 [JavaScript engine](/more/glossary-of-terms#javascript-engine) 中不可用语言特性的转译器。[Metro](/more/glossary-of-terms#metro-bundler) 内部使用 Babel。
项目可以通过修改项目目录中的 [**babel.config.js**](/versions/latest/config/babel) 文件来配置 Babel 的使用方式。在使用 [Expo CLI](/more/glossary-of-terms#expo-cli) 时,这个文件是可选的。Expo 项目应扩展默认的 Babel 预设 [`babel-preset-expo`](https://github.com/expo/expo/tree/main/packages/babel-preset-expo)。
### Bare workflow
描述原生项目(位于 **android** 和 **ios** 目录中)在 Git 中进行版本管理并由手动维护的方式。这通常适用于**现有的“裸” React Native 应用**,你需要手动对原生项目进行更改。它具有较高的定制自由度,但也带来了较高的维护成本。
这与使用 [app config 和 prebuild](/workflow/continuous-native-generation) 相对,后者中的原生项目不进行版本管理。相反,它们会按需通过 `npx expo prebuild` 生成,这也是[推荐的方式](/workflow/continuous-native-generation)。
### Bun
一个 JavaScript 运行时,也是 Node.js 的可直接替代方案。Bun 也可用作 [JavaScript 的包管理器](/more/glossary-of-terms#package-manager)。有关与 Expo 和 EAS 一起使用的更多信息,请参阅 [使用 Bun](/guides/using-bun) 指南。
### CocoaPods
用于将原生模块链接到原生 iOS 项目的 iOS 包管理器。该包管理器通过 **ios/Podfile** 文件进行配置,并在用户于 **ios** 目录中运行 `pod install` 时更新。
### Community Autolinking
这是 React Native 社区对 [Expo Autolinking](/more/glossary-of-terms#expo-autolinking) 的[fork](https://github.com/react-native-community/cli/issues/248#issue-422591744)。模块的链接需求与 [Expo Autolinking](/more/glossary-of-terms#expo-autolinking) 不同,但实现相同。
### Config introspection
一种在内存中评估 [`npx expo prebuild`](/more/glossary-of-terms#prebuild) 结果而不持久化任何代码更改的过程。它用于 [Auto Capability Signing](/more/glossary-of-terms#auto-capability-signing),以在不生成任何原生代码的情况下确定 entitlements 文件的外观。该过程也用于 [VS Code Expo Tools](/more/glossary-of-terms#vs-code-expo-tools) 扩展中,以调试 [Config Mods](/more/glossary-of-terms#config-mods)。
### Config Mods
附加到 [app config](/more/glossary-of-terms#app-config) 上、供 [Prebuild](/more/glossary-of-terms#prebuild) 使用的异步函数。这些函数会接受单个原生文件进行修改,例如 **AndroidManifest.xml** 或 **Info.plist**。Config mods 会串联起来,并来自 `@expo/config-plugins` 包。有关更多信息,请参阅 [Config plugins](/config-plugins/introduction)。
### Config Plugin
用于将 [config mods](/more/glossary-of-terms#config-mods) 附加到 [app Config](/more/glossary-of-terms#app-config) 上、供 [Prebuild](/more/glossary-of-terms#prebuild) 使用的 JavaScript 函数。有关更多信息,请参阅 [Config Plugins](/config-plugins/introduction)。
### Continuous Native Generation (CNG)
描述从一组输入生成原生项目的抽象概念。在 Expo 的语境中,CNG 通过 [`prebuild`](/more/glossary-of-terms#prebuild) 命令实现。更多信息请参阅 [Continuous Native Generation](/workflow/continuous-native-generation)。
### create-expo-app
一个独立的命令行工具(CLI),用于启动已安装 `expo` 包的新 React Native 应用。更多信息请参阅 [`create-expo-app` 参考](/more/create-expo)。
### create-react-native-app
一个独立的命令行工具(CLI),用于启动已安装 `expo` 包并生成原生代码的新 React Native 应用。该 CLI 还支持从 [expo/examples](https://github.com/expo/examples) 中的示例项目进行启动。
可以通过运行以下任一命令来使用此包:
- `npx create-expo-app`
- `yarn create expo-app`
- `npm create expo-app`
### Dangerous mods
在 [prebuild](/more/glossary-of-terms#prebuild) 期间对原生项目应用不稳定更改的 [modifiers](/more/glossary-of-terms#config-mods)。使用这些修改器具有不可预测性,并且在 [Expo SDK](/more/glossary-of-terms#expo-sdk) 的主要版本升级之间容易出现破坏性变更。有关更多信息,请参阅 [Using a dangerous mod](/config-plugins/dangerous-mods)。
### Development build
开发构建是包含 `expo-dev-client` 包的应用调试构建。它类似于 [Expo Go](/more/glossary-of-terms#expo-go) 的进化版,不受 Expo Go 的限制,并且可以根据应用需求进行定制。
这是使用 Expo 构建生产级应用的推荐方式。有关更多信息,请参阅 [Development builds](/get-started/set-up-your-environment?mode=development-build)。
### Dev clients
`expo-dev-client` 是一个允许你创建开发构建并包含实用开发工具的库。你也可能会遇到“custom dev client”这一说法,它是 [Development builds](/more/glossary-of-terms#development-build) 的同义词。
### Development server
开发服务器(或 dev server)是本地启动的服务器,通常通过从 [Expo CLI](/more/glossary-of-terms#expo-cli) 运行 `npx expo start` 来启动。
开发服务器通常托管在 `http://localhost:8081`。它在 `/` 下提供一个 [manifest](/more/glossary-of-terms#manifest),客户端通过它来请求 bundler 提供的 JavaScript bundle。
### Expo Application Services (EAS)
[Expo Application Services (EAS)](/eas) 是为 Expo 和 React Native 应用深度集成的云服务,例如 [EAS Build](/build/introduction)、[EAS Submit](/submit/introduction)、[EAS Update](/eas-update/introduction)、[EAS Metadata](/eas/metadata)、[EAS Insights](/eas-insights/introduction)、[EAS Hosting](/eas/hosting/introduction) 和 [EAS Workflows](/eas/workflows/introduction)。
### EAS Build
[EAS Build](/build/introduction) 是 [EAS](/more/glossary-of-terms#expo-application-services-eas) 的云服务,用于为 Expo 和 React Native 应用构建 Android 和 iOS 二进制文件。EAS Build 可用于构建 [development builds](/more/glossary-of-terms#development-build) 和 [standalone apps](/more/glossary-of-terms#standalone-app)。
### EAS CLI
用于与 EAS 协作的命令行工具。有关更多信息,请参阅 [EAS CLI](/eas/cli) 参考。
### EAS Config
用于配置 [EAS CLI](/more/glossary-of-terms#eas-cli) 的 **eas.json** 文件。有关更多信息,请参阅 [使用 eas.json 配置 EAS Build](/build/eas-json)。
### EAS Hosting
[EAS Hosting](/eas/hosting/introduction) 是 [EAS](/more/glossary-of-terms#expo-application-services-eas) 的云服务,可快速部署使用 [Expo Router](/more/glossary-of-terms#expo-router) 和 [React Native Web](/more/glossary-of-terms#react-native-web) 构建的 Web 项目。
### EAS Insights
[EAS Insights](/eas-insights/introduction) 是 [EAS](/more/glossary-of-terms#expo-application-services-eas) 的云服务,为 Expo 项目提供使用情况、性能和覆盖范围信息。它使用 `expo-insights` 库将事件从应用发送到 EAS Insights。
### EAS Metadata
一个用于以 JSON 形式上传和下载 Apple App Store 元数据的命令行工具。该工具可在 [EAS CLI](/more/glossary-of-terms#eas-cli) 包中使用,应当用于改进 iOS 提交流程。有关更多信息,请参阅 [EAS Metadata](/eas/metadata)。
### EAS Update
1. 来自 [EAS](/more/glossary-of-terms#expo-application-services-eas) 的云托管服务 [EAS Update](/eas-update/introduction),用于 OTA 更新。
2. 来自 [EAS CLI](/more/glossary-of-terms#eas-cli) 的 CLI 命令 `eas update`,用于将静态文件发布到云托管服务。
### EAS Workflows
[EAS Workflows](/eas/workflows/introduction) 是 [EAS](/more/glossary-of-terms#expo-application-services-eas) 的 CI/CD 服务,可让团队自动化重复任务,例如构建 Android 和 iOS 二进制文件、发布空中更新、提交到应用商店、使用 Maestro 运行 E2E 测试,以及将 Web 应用部署到 [EAS Hosting](/eas/hosting/introduction)。Workflows 通过 **.eas/workflows** 目录下的 YAML 文件进行配置。
### Emulator
Emulator 用于描述计算机上的 Android 设备软件模拟器。通常,iOS 模拟器被称为 [Simulator](/more/glossary-of-terms#simulator)。
### Entry point
entry point 通常指用于加载应用的初始 JavaScript 文件。在使用 [Expo CLI](/more/glossary-of-terms#expo-cli) 的应用中,默认入口点是 **./node_modules/expo/AppEntry.js**,它会简单地从项目根目录导入 **App.js** 文件,并将其注册为原生应用中的初始组件。
### Experience
应用的同义词,通常暗示其更偏向一次性使用且范围更小,有时带有艺术性和奇趣风格。
### Expo Atlas
[Expo Atlas](/atlas/introduction) 是一个用于可视化 JavaScript bundle 的工具。它可用于检查 bundle 大小,并识别哪些库对生产 bundle 有贡献。
### Expo Autolinking
原始的 [Autolinking](/more/glossary-of-terms#autolinking) 系统是为使用 `expo-modules-core` 的项目设计的。该系统根据库根目录中是否存在 **expo-module.config.json** 来链接模块。
### Expo CLI
用于与 Expo 协作的命令行工具。此术语现在指 [Local Expo CLI](/more/glossary-of-terms#local-expo-cli),但历史上指的是 [Global Expo CLI](/more/glossary-of-terms#global-expo-cli)。有关更多信息,请参阅 [Expo CLI](/more/expo-cli)。
### Expo client
[Expo Go](/more/glossary-of-terms#expo-go) 应用的旧名称。
### Expo Doctor
[Expo Doctor](/develop/tools#expo-doctor) 是一个用于诊断 Expo 项目问题的命令行工具。使用时,请在项目目录中运行 `npx expo doctor`。
### Expo export
指来自 [Expo CLI](/more/glossary-of-terms#expo-cli) 的命令 `npx expo export`。该命令用于打包应用的 JavaScript 和资源,然后将它们导出到一个静态目录中,静态目录可上传到 [EAS Update](/more/glossary-of-terms#eas-update) 等托管服务,并嵌入到 [native runtime](/more/glossary-of-terms#native-runtime) 中供离线使用。
### Expo Fingerprint
[`@expo/fingerprint`](/versions/latest/sdk/fingerprint) 库会对决定项目原生构建的文件和配置进行哈希处理(应用依赖、定制原生代码、原生项目文件和配置)。该哈希代表原生层状态,因此工具可以在不重新构建的情况下判断某个 TypeScript/JavaScript bundle 是否与给定构建兼容。主要用于 EAS Update 的 fingerprint runtime version policy,以及用于 CI/CD 自动化的 EAS Workflows。
### Expo Go
Android 和 iOS 应用,用作学习和试验 React Native 的沙盒环境。
由于其限制(例如无法包含自定义原生代码),不建议用于构建和分发生产应用。相反,请使用 [development build](/more/glossary-of-terms#development-build)。
### Expo install
指来自 [Expo CLI](/more/glossary-of-terms#expo-cli) 的命令 `npx expo install`。该命令用于安装包含可与项目当前安装的 `expo` 版本配合使用的 [native modules](/more/glossary-of-terms#native-module) 的 npm 包。并非所有包都受支持。该命令封装了全局安装的 [package managers](/more/glossary-of-terms#package-manager)。
### Expo MCP server
[Expo MCP(Model Context Protocol)服务器](/eas/ai/mcp) 是 Expo 托管的远程服务器,可与 Claude Code、Cursor、VS Code 等 AI 辅助工具集成。它使这些工具能够直接与您的 Expo 项目交互。
### Expo Module Config
位于 [native module](/more/glossary-of-terms#native-module) 根目录中的名为 **expo-module.config.json** 的文件。有关更多信息,请参阅 [Module Config](/modules/module-config)。
### Expo Modules API
[Expo Modules API](/modules/module-api) 是一个跨平台 API,用于用 Kotlin 和 Swift 编写原生模块,为你的应用添加新能力。该 API 由库 `expo-modules-core` 提供,而该库包含在 `expo` 包中。
### Expo Orbit
[Expo Orbit](/build/orbit) 是一款适用于 macOS 和 Windows 的应用,可更快地在设备或模拟器上安装并启动来自 EAS、本地文件或 Snack 项目的构建或更新。
### Expo Router
[Expo Router](/router/introduction) 是适用于 React Native 和 Web 应用的基于文件的路由器。它允许你管理应用中各屏幕之间的导航,使用户能够通过在多个平台(Android、iOS 和 Web)上使用相同的组件,无缝地在应用 UI 的不同部分之间移动。
### Expo SDK
一组包含 [native modules](/more/glossary-of-terms#native-module) 的 [npm](/more/glossary-of-terms#npm) 包,为相机、推送通知、联系人、文件系统等设备/系统功能提供访问能力。
- 在可能的情况下,每个包都支持 Android、iOS 和 web。
- 接口完全使用 [TypeScript](/more/glossary-of-terms#typescript) 编写。
- Expo SDK 中的所有包彼此兼容,并且可以安全地一起编译。
- SDK 中的任何包都可以在任何 [React Native](/more/glossary-of-terms#react-native) 应用中使用,只需最少且共享的设置。[了解更多](/bare/installing-expo-modules)。
- 所有包都是[开源](https://github.com/expo/expo/tree/main/packages)的,可以自由定制。
### Expo start
指来自 [Expo CLI](/more/glossary-of-terms#expo-cli) 的命令 `npx expo start`。该命令用于启动本地 [development server](/more/glossary-of-terms#development-server),由 [client](/more/glossary-of-terms#expo-client) 连接以与 [Metro bundler](/more/glossary-of-terms#metro-bundler) 交互。
### Fabric
React Native 的渲染系统,用于创建和管理原生视图。有关更多信息,请参阅 [Fabric Renderer](https://reactnative.dev/architecture/fabric-renderer)。
### FYI
有时也称为 **Expo FYI**,是位于 [expo.fyi](https://expo.fyi/) 的一系列针对复杂问题的定制解决方案。FYI 链接被广泛用于 Expo 的开发者工具中,以帮助为用户提供更好的开发体验。
### Gradle
Gradle 是一种用于多语言软件开发的构建自动化工具。它用于构建 Android 应用。它在编译、打包、测试、部署和发布等任务中控制开发流程。
### Hermes engine
由 [Meta](/more/glossary-of-terms#meta) 专为 [React Native](/more/glossary-of-terms#react-native) 使用而开发的 [JavaScript engine](/more/glossary-of-terms#javascript-engine)。Hermes 具有提前静态优化和紧凑字节码,以提升面向移动设备的性能,并且是默认的 JS 引擎。
### iOS
用于 iPhone、iPad 和 Apple TV 的操作系统。[Expo Go](/more/glossary-of-terms#expo-go) 目前运行于 iPhone 和 iPad 的 iOS 上。
### JavaScript engine
一种可在设备上执行 JavaScript 的原生包。在 React Native 中,我们主要使用 [Meta](/more/glossary-of-terms#meta) 的 [Hermes](/more/glossary-of-terms#hermes-engine)。其他选项包括 Apple 的 [JavaScriptCore](/more/glossary-of-terms#javascriptcore-engine) 以及 Google 的 V8。
### JavaScriptCore engine
由 Apple 开发并内置于 [iOS](/more/glossary-of-terms#ios) 的 [JavaScript engine](/more/glossary-of-terms#javascript-engine)。React Native for [Android](/more/glossary-of-terms#android) 也可以使用一个版本的 JavaScriptCore 以保持一致性。使用 JavaScriptCore 进行调试不如实现了 [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) 的 V8 或 [Hermes](/more/glossary-of-terms#hermes-engine) 那么成熟。
### Linking
Linking 可以指 [类似于在 Web 上链接到网站那样,深度链接到应用中](/linking/overview),也可以指 [autolinking](/more/glossary-of-terms#autolinking)。
### Local Expo CLI
包 `@expo/cli` 会随着 `expo` 包一起安装。这有时被称为“版本化 Expo CLI”,因为它安装在用户的项目中,而不是已弃用的、全局安装的 `expo-cli`。
### Manifest
Expo 应用 manifest 类似于 [web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest)。它提供 Expo Go 需要知道如何运行应用的信息以及其他相关数据。
### Meta
Meta 曾用名 Facebook,是开发 [React Native](/more/glossary-of-terms#react-native)、[Metro Bundler](/more/glossary-of-terms#metro-bundler)、[Hermes Engine](/more/glossary-of-terms#hermes-engine)、[Yoga](/more/glossary-of-terms#yoga) 等项目的公司。Expo 团队与 Meta 合作,以提供尽可能好的开发者体验。
### Metro bundler
用于将 JavaScript 文件和资源转换为可在 [native runtime](/more/glossary-of-terms#native-runtime) 上运行的格式的 bundler。该 bundler 由 [Meta](/more/glossary-of-terms#meta) 维护,并用于 React Native(包括 web)应用。有关更多信息,请参阅 [Metro documentation](https://metrobundler.dev/)。
### Metro config
用于配置 [Metro bundler](/more/glossary-of-terms#metro-bundler) 的 **metro.config.js** 文件。在使用 [Expo CLI](/more/glossary-of-terms#expo-cli) 时,这应扩展包 `@expo/metro-config`。有关更多信息,请参阅 [Customizing Metro](/guides/customizing-metro)。
### Monorepo
一个包含多个子项目、并通过包管理器相互关联的项目。Monorepo 是维护跨平台应用代码库的绝佳方式。
### Native directory
React Native 生态系统有成千上万的库。如果没有专门构建的工具,就很难了解这些库是什么、搜索它们、判断质量、试用它们,以及筛选出不适合你项目的库(有些不适用于 Expo,有些不适用于 Android 或 iOS)。[React Native Directory](https://reactnative.directory/) 是一个旨在解决这一问题的网站,我们建议你使用它来寻找项目中要使用的包。
### Native module
用原生代码编写的模块,通过 JS 全局对象向 JavaScript 引擎暴露原生平台功能。通常通过 `import { NativeModules } from 'react-native';` 访问这些功能。
### Native runtime
包含 [JavaScript engine](/more/glossary-of-terms#javascript-engine) 且能够运行 React 应用的原生应用。这包括 [Expo Go](/more/glossary-of-terms#expo-go)、[development build](/more/glossary-of-terms#development-build)、[standalone apps](/more/glossary-of-terms#standalone-app),甚至像 Chrome 这样的 Web 浏览器。
### npm
[npm](https://www.npmjs.com/) 是 [JavaScript 的包管理器](/more/glossary-of-terms#package-manager) 以及存放这些包的注册表。
### Package manager
自动化安装、升级、配置和移除项目中库(也称为依赖项)的过程。参见 [Bun](/more/glossary-of-terms#bun)、[npm](/more/glossary-of-terms#npm)、[pnpm](/more/glossary-of-terms#pnpm) 和 [Yarn](/more/glossary-of-terms#yarn)。
### Package manager workspaces
Expo 用户推荐的 [monorepo](/more/glossary-of-terms#monorepo) 方案。有关如何为受支持的包管理器配置 workspaces 的更多信息,请参阅 [使用 Monorepo](/guides/monorepos) 指南。
### Platform extensions
Platform extensions 是 [Metro bundler](/more/glossary-of-terms#metro-bundler) 的一项功能,它允许用户根据特定文件名按平台替换文件。例如,如果一个项目有 **.index.js** 文件和 **.index.ios.js** 文件,那么在为 iOS 打包时会使用 **index.ios.js**,而在为所有其他平台打包时会使用 **index.js** 文件。
默认情况下,platform extensions 会在 `@expo/metro-config` 中按照以下公式解析:
- Android: **\*.android.js**, **\*.native.js**, **\*.js**
- iOS: **\*.ios.js**, **\*.native.js**, **\*.js**
- Web: **\*.web.js**, **\*.js**
### pnpm
[pnpm](https://pnpm.io/) 是一个 [JavaScript 的包管理器](/more/glossary-of-terms#package-manager),专注于提高磁盘空间效率。
### Prebuild
根据 [应用配置](/more/glossary-of-terms#app-config) 为 React Native 项目生成临时的本地 **android** 和 **ios** 目录的过程。该过程通过在项目目录中从 [Expo CLI](/more/glossary-of-terms#expo-cli) 运行命令 `npx expo prebuild` 来执行。
有关更多信息,请参见 [Prebuild 模板](/more/glossary-of-terms#prebuild-template) 和 [自动链接](/more/glossary-of-terms#autolinking)。
### Prebuild 模板
React Native 项目模板作为 [Prebuild](/more/glossary-of-terms#prebuild) 的第一步使用。该模板会随 [Expo SDK](/more/glossary-of-terms#expo-sdk) 进行版本控制,并且模板会根据项目中安装的 `expo` 版本来选择。模板克隆完成后,`npx expo prebuild` 会评估 [应用配置](/more/glossary-of-terms#app-config) 并运行会修改模板中各种文件的 [配置修改](/more/glossary-of-terms#config-mods)。
虽然可以使用 `npx expo prebuild --template /path/to/template` 标志来更改模板,但默认的 prebuild 模板包含 `npx expo prebuild` 命令所依赖的重要初始默认值。
默认模板目前位于 [`expo-template-bare-minimum`](https://github.com/expo/expo/tree/main/templates/expo-template-bare-minimum)。
### 发布
我们将“publish”作为“deploy”的同义词使用。当你发布一个应用时,它会通过 Expo Go 变为可通过一个持久 URL 访问;或者在 [独立应用](/more/glossary-of-terms#standalone-app) 的情况下,它会更新该应用。
### React Native
[React Native](https://reactnative.dev/) 让你只用 JavaScript 就能构建移动应用。它使用与 React 相同的设计,使你能够通过声明式组件组合出丰富的移动 UI。
### React Native Web
建立在 `react-dom` 之上的高性能抽象层,使 [React Native](/more/glossary-of-terms#react-native) 的核心原语能够在浏览器中运行。面向 Web 的 React Native(RNW)由 X 开发,目前用于他们的 [主站](https://x.com)。[Expo SDK](/more/glossary-of-terms#expo-sdk) 和 [Expo CLI](/more/glossary-of-terms#expo-cli) 对 RNW 提供一等支持。
### React Navigation
React Native 应用首选的导航库,由 Expo 团队开发并赞助。
### 远程调试
远程调试是 React Native 应用的一种已弃用的调试方式。如今更好的替代方案是使用 [Hermes](/more/glossary-of-terms#hermes-engine),因为你可以将 React Native DevTools 连接到它。
它也被称为 Async Chrome 调试,是一种用于调试 React Native 应用的实验性系统。该系统通过在 Chrome 标签页的 web worker 中执行应用的 JavaScript,然后通过 websocket 将原生命令发送到原生设备来工作。
### 模拟器
iOS 设备模拟器,可在 macOS 上运行(或在 [Snack](/more/glossary-of-terms#snack) 中运行),让你在没有实体设备的情况下开发应用。
### Slug
[应用配置](/more/glossary-of-terms#appjson) 中的 `slug` 是项目的一个便于 URL 使用的名称。它在你的 Expo 账户中是唯一的。
### Snack
[Snack](https://snack.expo.dev/) 是一个基于浏览器的开发环境,你可以在其中构建 Expo [体验](/more/glossary-of-terms#experience),而无需在手机或电脑上安装任何工具。
### Software Mansion
位于波兰克拉科夫的一家开发机构。`react-native-gesture-handler`、`react-native-screens` 和 `react-native-reanimated` 的维护者。Expo 的平台团队由来自 Software Mansion 的多名外包人员组成。Software Mansion 的所有核心 React Native 库都在 [Expo Go](/more/glossary-of-terms#expo-go) 中受支持。
### 独立应用
“生产构建”的同义词。可提交到 Google Play 商店或 Apple App Store 的应用二进制文件。更多信息请参见 [为应用商店构建项目](/deploy/build-project) 或 [在本地或自有基础设施上运行构建](/build-reference/local-builds)。
### 商店配置
用于配置 [EAS Metadata](/more/glossary-of-terms#eas-metadata) 的 **store.config.json** 文件。该文件可以通过现有的 App Store 条目使用 `eas metadata:pull` 生成。
### Sweet API
用于编写 React Native 模块的 Swift 和 Kotlin API。此 API 由库 `expo-modules-core` 提供,而该库随 `expo` 包一同发布。更多信息请参见 [模块 API](/modules/module-api)。
### TypeScript
TypeScript 是一种强类型编程语言,建立在 JavaScript 之上,可为任何规模的项目提供更好的工具支持。Expo SDK 使用 TypeScript 编写,我们强烈推荐使用它。更多信息请参见我们的 [TypeScript 指南](/guides/typescript)。
### 更新
传统上,Android 和 iOS 应用的更新方式是向 App Store 和 Play 商店提交一个更新后的二进制文件。Updates 允许你向应用推送更新,而无需承担向商店提交新版本的开销。更多信息请参见 [发布](/eas-update/introduction) 文档。
### VS Code Expo Tools
用于改善开发者在处理应用配置文件时体验的 VS Code 扩展。此扩展为 [应用配置](/more/glossary-of-terms#app-config)、[商店配置](/more/glossary-of-terms#store-config)、[Expo 模块配置](/more/glossary-of-terms#expo-module-config) 和 [EAS 配置](/more/glossary-of-terms#eas-config) 提供自动补全和智能提示。更多信息请参见 [VS Code Expo Tools 扩展](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools)。
### Watchman
[Metro](/more/glossary-of-terms#metro-bundler) 用于在开发期间执行热重载的文件监视器。Watchman 包含原生代码,若全局安装可能会导致问题。Watchman 由 [Meta](/more/glossary-of-terms#meta) 维护。
### webpack
[Expo CLI](/more/glossary-of-terms#expo-cli) 用于开发 [`react-native-web`](/more/glossary-of-terms#react-native-web) 应用的已弃用打包器。
### Yarn
[Yarn](https://yarnpkg.com/) 是一个由 Meta 创建的 [JavaScript 的包管理器](/more/glossary-of-terms#package-manager)。它有两个主线版本:[Yarn v1(Classic)](https://classic.yarnpkg.com/lang/en/) 和 [Yarn Berry](https://github.com/yarnpkg/berry)。
### Yoga
React Native 内部使用的原生跨平台库,用于向原生视图提供 [CSS FlexBox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout/Basic_concepts_of_flexbox) 支持。React Native 的样式会传递给 Yoga,以对屏幕上的元素进行布局和样式设置。更多信息请参见 [Yoga](https://github.com/facebook/yoga) 文档。
---
---
title: qr.expo.dev
description: qr.expo.dev 上二维码生成器的参考文档。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/more/qr-codes/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# qr.expo.dev
qr.expo.dev 上二维码生成器的参考文档。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
qr.expo.dev 是一个生成带有 Expo 品牌的 QR 码的云函数。该函数会为 [EAS Update](/eas-update/introduction) 创建 QR 码,这些 QR 码用于在 [开发构建](/develop/development-builds/introduction) 和 Expo Go 中预览更新。
例如,如果你和你的团队有一个开发构建,并且你想在某个构建的频道上加载最新更新,你可以前往以下端点生成 QR 码:
```text
https://qr.expo.dev/eas-update?projectId=your-project-id&runtimeVersion=your-runtime-version&channel=your-channel
```
这将生成以下 QR 码 SVG:
这个 QR 码代表以下 URL:
```text
exp+your-slug://expo-development-client/?url=https://u.expo.dev/your-project-id?runtime-version=your-runtime-version&channel-name=your-channel
```
此 URL 会深度链接到一个开发构建,并指示它获取指定频道上的最新更新。
> 如果共享 URL 更方便,你可以在查询参数中添加 `format=url` 来直接请求 URL。
## General
以下参数适用于 `/eas-update` 端点。
### Base query parameters
以下基础查询参数可以包含在发往 `/eas-update` 的任何请求中。
| Param | Required | Default | Description |
| --- | --- | --- | --- |
| `slug` | No | exp | 使用 [app config](/workflow/configuration) 中的 [`slug`](/versions/latest/config/app#slug) 来定位开发构建。否则使用 "exp" 来定位 Expo Go。 |
| `appScheme` (deprecated) | No | exp | 已被 `slug` 替换。请改用 `slug`。 |
| `host` | No | u.expo.dev | 处理更新请求的服务器主机名。 |
| `format` | No | svg | 端点默认返回 SVG。若要接收纯文本 URL,请使用 `url`。 |
### Update by device traits
预览和生产构建会向 EAS Update 服务发出带有 `runtimeVersion` 和 `channel` 属性的请求。你可以使用以下查询参数模拟这种行为:
| Param | Required | Description |
| --- | --- | --- |
| `projectId` | Yes | 项目的 ID |
| `runtimeVersion` | Yes | 构建的 [runtime version](/eas-update/runtime-versions) |
| `channel` | Yes | 构建的频道名称 |
#### Example
```text
https://qr.expo.dev/eas-update?projectId=your-project-id&runtimeVersion=your-runtime-version&channel=your-channel
```
### Update by ID
你可以为给定的平台特定 ID 创建一个特定更新的 QR 码。
| Param | Required | Description |
| --- | --- | --- |
| `updateId` | Yes | 更新的 ID |
#### Example
```text
https://qr.expo.dev/eas-update?updateId=your-update-id
```
### Update by group ID
你可以为给定的更新组 ID 创建一个更新组的 QR 码。
| Param | Required | Description |
| --- | --- | --- |
| `projectId` | Yes | 项目的 ID |
| `groupId` | Yes | 更新组的 ID |
#### Example
```text
https://qr.expo.dev/eas-update?projectId=your-project-id&groupId=your-update-id
```
### Update by branch ID
你可以使用分支的 ID 创建一个 QR 码,它将返回该分支上可用的最新更新。
| Param | Required | Description |
| --- | --- | --- |
| `projectId` | Yes | 项目的 ID |
| `branchId` | Yes | 分支的 ID |
#### Example
```text
https://qr.expo.dev/eas-update?projectId=your-project-id&branchId=your-branch-id
```
### Update by channel ID
你可以使用频道的 ID 创建一个 QR 码,它将返回映射到该频道的分支上的最新可用更新。
| Param | Required | Description |
| --- | --- | --- |
| `projectId` | Yes | 项目的 ID |
| `channelId` | Yes | 频道的 ID |
#### Example
```text
https://qr.expo.dev/eas-update?projectId=your-project-id&channelId=your-channel-id
```
---
---
title: 发布状态
description: 了解 alpha、preview、beta 和 stable 发布状态,以及它们在使用 Expo SDK 和 Expo Application Services(EAS)时如何影响功能稳定性。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/more/release-statuses/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# 发布状态
了解 alpha、preview、beta 和 stable 发布状态,以及它们在使用 Expo SDK 和 Expo Application Services(EAS)时如何影响功能稳定性。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
Expo 使用不同的发布状态来表示其工具和服务的稳定性与就绪程度。了解这些状态可以帮助你在项目中就要使用哪些功能和版本做出更明智的决定。
## Alpha
Alpha 功能可供早期测试,但可能存在较大的限制。这些功能处于开发的最早阶段,会与社区分享以收集反馈并塑造其发展方向。
**可以预期:**
- API 可能会在不提升主版本号的情况下发生破坏性变更
- 实现可能会根据反馈发生重大变化
- 可能存在已知错误或性能问题
- 不建议用于生产应用
Alpha 功能是影响 Expo 未来的机会。我们鼓励你在开发环境中测试这些功能,并[提供反馈](https://expo.dev/contact),帮助我们在它们面向更广泛的受众之前进一步完善。
## Preview
Preview 功能提供新功能的一部分的早期预览。与 alpha 版本不同,preview 功能以最小开销和有限范围为设计目标,但它们尚未功能完备。
**可以预期:**
- 只涵盖一部分聚焦的功能,而非完整功能集
- 以最小开销设计,但尚未针对所有生产场景进行充分验证
- 随着功能进一步完善,API 可能会演进
- 可在生产环境中使用,但需要经过充分测试,不过功能有限
preview 的目的是尽早分享新功能,并在进一步完善之前收集关于特定部分的反馈。你的意见将直接帮助塑造该功能的方向。[分享你的反馈](https://expo.dev/contact),帮助我们确定下一步优先构建什么。
## Beta
Beta 功能已经功能完备,正在进行最终验证。这些功能的核心能力已经实现,正为稳定发布做准备。
**可以预期:**
- 核心功能已完成,API 形态大体已定
- 可能存在正在处理的小错误或边缘情况
- 可能发生破坏性变更,但除非发现严重问题,否则可能性不大
- 可在生产环境中使用,但需要经过充分测试
Beta 功能已准备好用于真实世界测试。虽然我们不预期会有重大变更,但如果你计划在生产环境中使用,我们建议进行彻底测试。[你的反馈](https://expo.dev/contact)在这个阶段能帮助我们在稳定发布前发现任何遗留问题。
## Stable
没有任何状态徽章的功能被视为 stable,并已完全发布,可用于生产环境。这些功能已经过充分测试,并遵循语义化版本控制来处理未来的任何变更。
**可以预期:**
- 可直接用于生产,并获得完整支持
- 破坏性变更只会在主版本发布时发生
- 性能和稳定性已经过验证
- 提供文档和示例
Stable 功能已准备好可用于任何应用。你可以依赖它们遵循语义化版本控制原则,这意味着破坏性变更只会在主版本更新中发生。
## Deprecated
Deprecated 功能是不再建议使用、并将在未来版本中移除的功能。我们会提供弃用警告,给开发者时间从这些功能迁移出去。
**可以预期:**
- 在使用 deprecated 功能时,文档和代码中会出现警告
- 不会再新增功能或改进
- 将在未来的主版本中移除
当你遇到一个 deprecated 功能时,我们建议尽快规划迁移到建议的替代方案,以确保你的项目保持最新并易于维护。
---
---
modificationDate: 2021 年 5 月 24 日
title: Expo 结构化字段值
description: 版本 0
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/technical-specs/expo-sfv-0/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo 结构化字段值
版本 0
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
HTTP 的结构化字段值,[IETF RFC 8941](https://tools.ietf.org/html/rfc8941),是一项旨在规范标头语法并促进嵌套数据的提案。
由于它仍处于进行中状态,Expo 维护了一个自定义版本,仅实现了 [IETF RFC 8941](https://tools.ietf.org/html/rfc8941) 中定义的协议的以下子集:
- 所有键值
- 字符串、整数和小数项
- 字典
---
---
modificationDate: March 13, 2023
title: Expo Updates v1
description: 版本 1
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/technical-specs/expo-updates-1/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo Updates v1
版本 1
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
## 介绍
这是 Expo Updates 的规范,它是一个用于向运行在多个平台上的 Expo 应用交付更新的协议。
### 一致性
符合规范的服务器和客户端库必须满足所有规范性要求。本文档通过描述性断言和具有明确定义含义的关键词来描述一致性要求。
本文档规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY” 和 “OPTIONAL” 应按照 [IETF RFC 2119](https://tools.ietf.org/html/rfc2119) 中的描述进行解释。这些关键词可以以小写形式出现,但除非明确声明为非规范性,否则仍保留其含义。
该协议的符合规范实现 MAY 提供额外功能,但在明确禁止的地方或会导致不符合规范的情况下 MUST NOT 提供额外功能。凡相关之处,符合规范的客户端应允许并忽略未知字段。
### 概述
符合规范的服务器和客户端库 MUST 遵循 [RFC 7231](https://tools.ietf.org/html/rfc7231) 中描述的 HTTP 规范,以及本规范中更精确的指导。
- _update_ 定义为一个 [_manifest_](/technical-specs/expo-updates-1#manifest-body) 以及 manifest 内引用的资源。
- [_directive_](/technical-specs/expo-updates-1#directive-body) 定义为来自服务器的一条消息,用于指示客户端执行某个操作。
Expo Updates 是一种用于向客户端组装并交付更新和指令的协议。
本规范的主要受众是 Expo Application Services,以及希望管理自己的更新服务器以满足内部需求的组织。
## 客户端
> 参见 [参考客户端库](https://github.com/expo/expo/tree/main/packages/expo-updates)。
运行符合规范的 Expo Updates 客户端库的应用 MUST 加载保存在客户端库更新数据库中的最新 _update_,并可能根据更新 manifest 的 [_metadata_](/technical-specs/expo-updates-1#manifest-body) 内容进行过滤。
以下内容描述了符合规范的 Expo Updates 客户端库 MUST 如何从符合规范的服务器获取新更新:
1. 客户端库 MUST 发起一个针对最新更新和指令的 [请求](/technical-specs/expo-updates-1#request),并在请求头中指定约束条件。
2. 如果收到了一个 [响应](/technical-specs/expo-updates-1#response),客户端库 MUST 处理其内容:
- 对于包含 _update_ 的响应,客户端库 SHALL 继续发起额外请求,下载并存储 manifest 中指定的任何新资源。manifest 和资源一起被视为一个新的 _update_。客户端库将编辑其本地状态,以反映新的 update 已被添加到本地存储中。它还会使用响应 [headers](/technical-specs/expo-updates-1#manifest-response-headers) 中找到的新 `expo-manifest-filters` 和 `expo-server-defined-headers` 更新本地状态。
- 对于包含 _directive_ 的响应,客户端库将根据指令类型消费该指令,并相应地编辑其本地状态。
## 请求
符合规范的客户端库 MUST 使用以下请求头发起 GET 请求:
1. `expo-protocol-version: 1`,用于指定本 Expo Updates 规范的第 1 版。
2. `expo-platform`,用于指定客户端运行的平台类型。
- iOS MUST 为 `expo-platform: ios`。
- Android MUST 为 `expo-platform: android`。
- 如果不是这些平台之一,服务器 SHOULD 返回 400 或 404
3. `expo-runtime-version` MUST 是与客户端兼容的运行时版本。运行时版本规定了客户端所运行的原生代码配置。它应在客户端构建时设置。例如,在 iOS 客户端中,该值可以设置在 plist 文件中。
4. 任何前一个响应的 [server defined headers](/technical-specs/expo-updates-1#response) 所规定的请求头。
符合规范的客户端库 MAY 基于 [支持的响应结构](/technical-specs/expo-updates-1#response) 发送 `accept: application/expo+json`、`accept: application/json` 或 `accept: multipart/mixed` 之一,尽管它 SHOULD 发送 `accept: application/expo+json, application/json, multipart/mixed`。符合规范的客户端库 MAY 按照 [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.1) 的规定使用 "q" 参数表达偏好,其默认值为 `1`。
配置为执行 [code signing](/technical-specs/expo-updates-1#code-signing) 验证的符合规范的客户端库 MUST 发送 `expo-expect-signature` 请求头,以表明它期望符合规范的服务器在 manifest 响应中包含 `expo-signature` 请求头。`expo-expect-signature` 是一个 [Expo SFV](/technical-specs/expo-sfv-0) 字典,其中 MAY 包含以下任意键值对:
- `sig` SHOULD 包含布尔值 `true`,以表明它要求符合规范的服务器在 `sig` 键中返回签名。
- `keyid` SHOULD 包含客户端将用于验证签名的公钥的 keyId
- `alg` SHOULD 包含客户端将用于验证签名的算法
示例:
```text
expo-protocol-version: 1
accept: application/expo+json;q=0.9, application/json;q=0.8, multipart/mixed
expo-platform: *
expo-runtime-version: *
expo-expect-signature: sig, keyid="root", alg="rsa-v1_5-sha256"
```
## 响应
符合规范的服务器 MUST 返回至少符合以下两种响应结构之一的响应,MAY 支持其中一种或两种响应结构;当请求了不受支持的响应结构时,服务器 SHOULD 返回 HTTP `406` 错误状态。如果服务器希望针对所请求的协议版本返回不兼容的响应,也 SHOULD 改为返回 HTTP `406` 错误状态。
- 对于 `content-type: application/json` 或 `content-type: application/expo+json` 的响应,[common response headers](/technical-specs/expo-updates-1#common-response-headers) 和 [other response headers](/technical-specs/expo-updates-1#other-response-headers) MUST 在响应头中发送,而 [manifest body](/technical-specs/expo-updates-1#manifest-body) MUST 在响应体中发送。此响应格式不支持多个响应部分,因此不支持 _directives_;当要提供的最新响应不是 _update_ 时,SHOULD 返回 HTTP `406` 错误状态。
- 对于 `content-type: multipart/mixed` 的响应,响应 MUST 按照 [multipart response](/technical-specs/expo-updates-1#multipart-response) 部分中的规定进行结构化。
- 没有任何部分的 [multipart response](/technical-specs/expo-updates-1#multipart-response) MAY 返回 HTTP `204` 状态且无内容,因此也没有 `content-type` 响应头。
update 和 headers 的选择取决于请求头的值。符合规范的服务器 MUST 返回按创建时间排序、满足 [request headers](/technical-specs/expo-updates-1#request) 所施加的所有参数和约束的最新 update。服务器 MAY 使用请求的任何属性,如其 headers 和源 IP 地址,在多个都满足请求约束的更新之间进行选择。
### 通用响应头
```text
expo-protocol-version: 1
expo-sfv-version: 0
expo-manifest-filters:
expo-server-defined-headers:
cache-control: *
content-type: *
```
- `expo-protocol-version` 描述了本规范中定义的协议版本,且 MUST 为 `1`。
- `expo-sfv-version` MUST 为 `0`。
- `expo-manifest-filters` 是一个 [Expo SFV](/technical-specs/expo-sfv-0) 字典。它用于根据 [manifest](/technical-specs/expo-updates-1#manifest-body) 中 `metadata` 属性的值,过滤客户端库存储的更新。如果筛选器中提到了某个字段,则相应 metadata 字段必须缺失或相等,更新才会被包含。客户端库 MUST 存储 manifest filters,直到它被更新的响应覆盖。
- `expo-server-defined-headers` 是一个 [Expo SFV](/technical-specs/expo-sfv-0) 字典。它定义了客户端库 MUST 存储的请求头,直到被更新的字典覆盖,并且它们 MUST 包含在之后每次 [update request](/technical-specs/expo-updates-1#request) 中。
- `cache-control` MUST 设置为一个足够短的时间段。建议使用 `cache-control: private, max-age=0`,以确保返回最新 manifest。设置更长的缓存时间可能导致返回过期更新。
- `content-type` MUST 通过 [RFC 7231](https://tools.ietf.org/html/rfc7231#section-3.4.1) 中定义的 _proactive negotiation_ 决定。由于客户端库 [要求](/technical-specs/expo-updates-1#request) 在每次 manifest 请求中发送 `accept` 请求头,因此这里总是会是 `application/expo+json`、`application/json`;否则请求将返回 `406` 错误。
### 其他响应头
```text
expo-signature: *
```
- `expo-signature` SHOULD 包含 manifest 的签名,以便在 [code signing](/technical-specs/expo-updates-1#code-signing) 的验证步骤中使用,前提是对 manifest 的请求包含了 `expo-expect-signature` 请求头。这是一个 [Expo SFV](/technical-specs/expo-sfv-0) 字典,其中 MAY 包含以下任意键值对:
- `sig` MUST 包含 manifest 的签名。此字段的名称与 `expo-expect-signature` 一致。
- `keyid` MAY 包含服务器用于对响应签名的密钥的 keyId。客户端 SHOULD 使用与此 `keyid` 匹配的证书来验证签名。
- `alg` MAY 包含服务器用于对响应签名的算法。客户端 SHOULD 仅在其与 `keyid` 所匹配证书定义的算法一致时使用此字段。
### 多部分响应
这种格式的更新响应由 [RFC 2046](https://tools.ietf.org/html/rfc2046#section-5.1) 中定义的 `multipart/mixed` MIME 类型定义。
此响应格式的头部是 [common response headers](/technical-specs/expo-updates-1#common-response-headers),但有以下例外:
- `content-type` SHOULD 具有 [RFC 2046](https://tools.ietf.org/html/rfc2046#section-5.1) 中定义的 `multipart/mixed` 值
部分的顺序不受严格限制。没有任何部分(零长度 body)的多部分响应应被视为无操作(没有可用的更新或指令),不过响应头 SHOULD 仍然发送,并由客户端处理。
每个部分定义如下:
1. 可选的 `"manifest"` 部分:
- MUST 具有分部头 `content-disposition: form-data; name="manifest"`。第一个参数(`form-data`)不一定需要是 `form-data`,但 `name` 参数必须取值为 `manifest`。
- MUST 具有分部头 `content-type: application/json` 或 `application/expo+json`。
- 如果正在使用 code signing,则 SHOULD 具有 [other response headers](/technical-specs/expo-updates-1#other-response-headers) 中定义的分部头 `expo-signature`。
- [manifest body](/technical-specs/expo-updates-1#manifest-body) MUST 作为分部内容发送。
2. 可选的 `"extensions"` 部分:
- MUST 具有分部头 `content-disposition: form-data; name="extensions"`。第一个参数(`form-data`)不一定需要是 `form-data`,但 `name` 参数必须取值为 `extensions`。
- MUST 具有分部头 `content-type: application/json`。
- [extensions-body](/technical-specs/expo-updates-1#extensions-body) MUST 作为分部内容发送。
3. 可选的 `"directive"` 部分:
- MUST 具有分部头 `content-disposition: form-data; name="directive"`。第一个参数(`form-data`)不一定需要是 `form-data`,但 `name` 参数必须取值为 `directive`。
- MUST 具有分部头 `content-type: application/json` 或 `application/expo+json`。
- 如果正在使用 code signing,则 SHOULD 具有 [other response headers](/technical-specs/expo-updates-1#other-response-headers) 中定义的分部头 `expo-signature`。
- [directive body](/technical-specs/expo-updates-1#directive-body) MUST 作为分部内容发送。
### Manifest body
定义为符合以下以 [TypeScript](https://www.typescriptlang.org/) 表示的 `Manifest` 定义以及每个字段详细说明的 JSON:
```ts
type Manifest = {
id: string;
createdAt: string;
runtimeVersion: string;
launchAsset: Asset;
assets: Asset[];
metadata: { [key: string]: string };
extra: { [key: string]: any };
};
type Asset = {
hash?: string;
key: string;
contentType: string;
fileExtension?: string;
url: string;
};
```
- `id`:该 ID MUST 唯一标识该 manifest,并且 MUST 是一个 UUID。
- `createdAt`:创建该更新的日期和时间至关重要,因为客户端库会选择最新的更新(受 `expo-manifest-filters` 请求头提供的任何约束影响)。该 datetime 应按照 [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) 格式化。
- `runtimeVersion`:可以是开发者定义的任意字符串。它规定了运行相关更新所需的原生代码配置。
- `launchAsset`:作为应用代码入口点的特殊资源。该资源会忽略 `fileExtension` 字段,并 SHOULD 省略。
- `assets`:更新 bundle 使用的资源数组,例如 JavaScript、图片和字体。在执行更新之前,所有资源(包括 `launchAsset`)都应下载到磁盘,并且应向应用代码提供 asset `key` 到磁盘位置的映射。
- 每个 asset 对象的属性:
- `hash`:文件的 Base64URL 编码 SHA-256 哈希,用于保证完整性。Base64URL 编码由 [IETF RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648#section-5) 定义。
- `key`:用于在更新的应用代码中引用此资源的键。例如,该键可由处理应用代码的单独构建步骤生成,例如打包器。
- `contentType`:文件的 MIME 类型,由 [RFC 2045](https://tools.ietf.org/html/rfc2045) 定义。例如 `application/javascript`、`image/jpeg`。
- `fileExtension`:在客户端保存文件时建议使用的扩展名。某些平台(如 iOS)要求某些文件类型必须带扩展名保存。扩展名 MUST 以前缀 `.` 开头。例如,**.jpeg**。在某些情况下,例如 launchAsset,此字段会被本地确定的扩展名所取代而忽略。如果该字段被省略且没有本地规定的扩展名,则资源将不带扩展名保存。例如,`./filename` 末尾没有 `.`。 符合规范的客户端 SHOULD 在文件扩展名非空但缺少 `.` 前缀时,为其添加 `.` 前缀。
- `url`:文件可获取的位置。
- `metadata`:与更新相关联的元数据。它是一个以字符串为值的字典。服务器 MAY 返回它希望用于过滤更新的任何内容。metadata MUST 满足随附的 `expo-manifest-filters` 请求头定义的过滤条件。
- `extra`:用于存储可选的 “extra” 信息,例如第三方配置。例如,如果更新托管在 Expo Application Services (EAS) 上,则可以包含 EAS 项目 ID:
```json
"extra": {
"eas": {
"projectId": "00000000-0000-0000-0000-000000000000"
}
}
```
### 扩展 body
定义为符合以下以 [TypeScript](https://www.typescriptlang.org/) 表示的 `Extensions` 定义以及每个字段详细说明的 JSON:
```ts
type Extensions = {
assetRequestHeaders: ExpoAssetHeaderDictionary;
...
}
type ExpoAssetHeaderDictionary = {
[assetKey: string]: {
[headerName: string]: string,
};
}
```
- `assetRequestHeaders`:MAY 包含一个头(key、value)对的字典,用于与资源请求一起发送。Key 和 value MUST 都是字符串。
### 指令 body
定义为符合以下以 [TypeScript](https://www.typescriptlang.org/) 表示的 `Directive` 定义以及每个字段详细说明的 JSON:
```ts
type Directive = {
type: string;
parameters?: { [key: string]: any };
extra?: { [key: string]: any };
};
```
- `type`:指令的类型。
- `parameters`:MAY 包含任何与 `type` 相关的附加信息。
- `extra`:用于存储可选的 “extra” 信息,例如第三方信息。例如,如果更新托管在 Expo Application Services (EAS) 上,则可以包含 EAS 项目 ID。
符合规范的客户端库和服务器 MAY 指定并实现适用于应用需求的特定指令类型。例如,到目前为止,Expo Application Services 使用了一种类型:`rollBackToEmbedded`,它指示 expo-updates 库使用宿主应用中嵌入的更新,而不是任何其他已下载的更新。
## 资源请求
符合规范的客户端库 MUST 对清单中指定的资源 URL 发起 GET 请求。客户端库 SHOULD 包含一个接受清单中指定的资源内容类型的标头。此外,客户端库 SHOULD 指定客户端库能够处理的压缩编码。
示例标头:
```text
accept: image/jpeg, */*
accept-encoding: br, gzip
```
符合规范的客户端库 MUST 还要为此资源键包含 [`assetRequestHeaders`](/technical-specs/expo-updates-1#manifest-extensions) 中包含的任何标头(键、值)对。
## 资源响应
位于特定 URL 的资源 MUST NOT 自创建以来被更改或移除,因为客户端库可能会在任何更新时随时获取资源。符合规范的客户端 MUST 验证资源的 base64url 编码 SHA-256 哈希与清单中该资源的 `hash` 字段匹配。
### 资源响应标头
资源 MUST 使用客户端根据请求的 `accept-encoding` 标头所支持的压缩格式进行编码。服务器 MAY 提供未压缩的资源。响应 MUST 包含一个 `content-type` 标头,其中包含该资源的 MIME 类型。 例如:
```text
content-encoding: br
content-type: application/javascript
```
建议为资源提供 `cache-control` 标头,并将其设置为较长的持续时间,因为位于给定 URL 的资源不得更改。例如:
```text
cache-control: public, max-age=31536000, immutable
```
### 压缩
资源 SHOULD 能够以 [Gzip](https://www.gnu.org/software/gzip/) 和 [Brotli](https://github.com/google/brotli) 压缩方式提供。
## 代码签名
Expo Updates 支持对清单和指令正文进行代码签名。对清单进行代码签名也会连带对资源进行签名,因为资源的哈希值存在于清单中,并会由符合规范的客户端进行验证。符合规范的客户端 MAY 使用私钥请求对清单或指令进行签名,然后在使用之前或在下载任何相应的清单资源之前,MUST 使用相应的代码签名证书验证清单或指令的签名。客户端 MUST 验证签名证书要么是自签名的受信任根证书,要么是由受信任根证书签名的证书链中的一部分。在任一情况下,根证书 MUST 嵌入在应用程序或设备的操作系统中。
---
---
title: app.json / app.config.js
description: Expo 应用配置中可用属性的参考。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/config/app/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# app.json / app.config.js
Expo 应用配置中可用属性的参考。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
以下是在 **app.json** 或 **app.config.json** 中 `"expo"` 键下可用的属性列表。这些属性也可以传递给 **app.config.js** 或 **app.config.ts** 的顶层对象。
[使用 app 配置进行配置](/workflow/configuration) — 有关应用配置、各种 app 配置文件之间的差异,以及如何动态使用它们的信息。
## 属性
### `name`
Type: `string`
The name of your app as it appears both within Expo Go and on your home screen as a standalone app.
Existing React Native app?
To change the name of your app, edit the 'Display Name' field in Xcode and the `app_name` string in `android/app/src/main/res/values/strings.xml`
### `description`
Type: `string`
A short description of what your app is and why it is great.
### `slug`
Type: `string`
A URL-friendly name for your project that is unique across your account.
### `owner`
Type: `string`
The name of the Expo account that owns the project. This is useful for teams collaborating on a project. If not provided, the owner defaults to the username of the current user.
### `currentFullName`
Type: `string`
The auto generated Expo account name and slug used for display purposes. It is not meant to be set directly. Formatted like `@username/slug`. When unauthenticated, the username is `@anonymous`. For published projects, this value may change when a project is transferred between accounts or renamed.
### `originalFullName`
Type: `string`
The auto generated Expo account name and slug used for services like Notifications and AuthSession proxy. It is not meant to be set directly. Formatted like `@username/slug`. When unauthenticated, the username is `@anonymous`. For published projects, this value will not change when a project is transferred between accounts or renamed.
### `sdkVersion`
Type: `string`
The Expo sdkVersion to run the project on. This should line up with the version specified in your package.json.
### `runtimeVersion`
One of types:
- `string` matching the following pattern: `^[a-zA-Z\d][a-zA-Z\d._+()-]{0,254}$`
- `string` matching the following pattern: `^exposdk:((\d+\.\d+\.\d+)|(UNVERSIONED))$`
- An `object` with the following properties:
#### `policy`
Type: `enum` • Path: `runtimeVersion.policy`
Valid values: `nativeVersion`, `sdkVersion`, `appVersion`, `fingerprint`.
Property indicating compatibility between a build's native code and an OTA update.
### `version`
Type: `string`
Your app version. In addition to this field, you'll also use `ios.buildNumber` and `android.versionCode` — read more about how to version your app [here](https://docs.expo.dev/distribution/app-stores/#versioning-your-app). On iOS this corresponds to `CFBundleShortVersionString`, and on Android, this corresponds to `versionName`. The required format can be found [here](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring).
Existing React Native app?
To change your app version, edit the 'Version' field in Xcode and the `versionName` string in `android/app/build.gradle`
### `platforms`
Type: `array`
Platforms that your project explicitly supports. If not specified, it defaults to `["ios", "android"]`. If `react-dom` is installed, `web` is also included by default.
Example
`[ "ios", "android", "web" ]`
### `githubUrl`
Type: `string`
If you would like to share the source code of your app on Github, enter the URL for the repository here and it will be linked to from your Expo project page.
Example
`"https://github.com/expo/expo"`
### `orientation`
Type: `enum` • One of: `default`, `portrait`, `landscape`
Locks your app to a specific orientation with portrait or landscape. Defaults to no lock. Valid values: `default`, `portrait`, `landscape`
### `userInterfaceStyle`
Type: `enum` • One of: `light`, `dark`, `automatic`
Configuration to force the app to always use the light or dark user-interface appearance, such as "dark mode", or make it automatically adapt to the system preferences. If not provided, defaults to `light`. Requires `expo-system-ui` be installed in your project to work on Android.
### `backgroundColor`
Type: `string`
The background color for your app, behind any of your React views. This is also known as the root view background color. Requires `expo-system-ui` be installed in your project to work on iOS.
6 character long hex color string, for example, `'#000000'`. Default is white: `'#ffffff'`
### `primaryColor`
Type: `string`
On Android, this will determine the color of your app in the multitasker. Currently this is not used on iOS, but it may be used for other purposes in the future.
6 character long hex color string, for example, `'#000000'`
### `icon`
Type: `string`
Local path or remote URL to an image to use for your app's icon. We recommend that you use a 1024x1024 png file. This icon will appear on the home screen and within the Expo Go app.
Existing React Native app?
To change your app's icon, edit or replace the files in `ios//Assets.xcassets/AppIcon.appiconset` (we recommend using Xcode), and `android/app/src/main/res/mipmap-`. Be sure to follow the guidelines for each platform ([iOS](https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/), [Android 7.1 and below](https://material.io/design/iconography/#icon-treatments), and [Android 8+](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive)) and to provide your new icon in each existing size.
### `androidStatusBar`
Type: `object`
Configuration for the status bar on Android. For more details navigate to [Configuring StatusBar](https://docs.expo.dev/guides/configuring-statusbar/).
#### `barStyle`
Type: `enum` • One of: `light-content`, `dark-content` • Path: `androidStatusBar.barStyle`
Configures the status bar icons to have a light or dark color. Valid values: `light-content`, `dark-content`. Defaults to `dark-content`
#### `backgroundColor`
Type: `string` • Path: `androidStatusBar.backgroundColor`
Specifies the background color of the status bar. Defaults to `#00000000` (transparent) for `dark-content` bar style and `#00000088` (semi-transparent black) for `light-content` bar style
6 character long hex color string `'#RRGGBB'`, for example, `'#000000'` for black. Or 8 character long hex color string `'#RRGGBBAA'`, for example, `'#00000088'` for semi-transparent black.
#### `hidden`
Type: `boolean` • Path: `androidStatusBar.hidden`
Instructs the system whether the status bar should be visible or not. Defaults to `false`
#### `translucent`
Type: `boolean` • Path: `androidStatusBar.translucent`
When false, the system status bar pushes the content of your app down (similar to `position: relative`). When true, the status bar floats above the content in your app (similar to `position: absolute`). Defaults to `true` to match the iOS status bar behavior (which can only float above content). Explicitly setting this property to `true` will add `android:windowTranslucentStatus` to `styles.xml` and may cause unexpected keyboard behavior on Android when using the `softwareKeyboardLayoutMode` set to `resize`. In this case you will have to use `KeyboardAvoidingView` to manage the keyboard layout.
### `developmentClient`
Type: `object`
Settings that apply specifically to running this app in a development client
#### `silentLaunch`
Type: `boolean` • Path: `developmentClient.silentLaunch`
If true, the app will launch in a development client with no additional dialogs or progress indicators, just like in a standalone app.
### `scheme`
One of types:
- `string` matching the following pattern: `^[a-z][a-z0-9+.-]*$`
`{ "type": "array", "items": { "type": "string", "pattern": "^[a-z][a-z0-9+.-]*$" } }`
URL scheme(s) to link into your app. For example, if we set this to `'demo'`, then demo:// URLs would open your app when tapped. This is a build-time configuration, it has no effect in Expo Go.
String beginning with a **lowercase** letter followed by any combination of **lowercase** letters, digits, "+", "." or "-"
Existing React Native app?
To change your app's scheme, replace all occurrences of the old scheme in `Info.plist` and `AndroidManifest.xml`
### `extra`
Type: `object`
Any extra fields you want to pass to your experience. Values are accessible via `Constants.expoConfig.extra` ([Learn more](https://docs.expo.dev/versions/latest/sdk/constants/#constantsmanifest))
### `updates`
Type: `object`
Configuration for the expo-updates library
#### `enabled`
Type: `boolean` • Path: `updates.enabled`
Whether the updates system will run. Defaults to true. If set to false, builds will only use code and assets bundled at time of build.
#### `checkAutomatically`
Type: `enum` • One of: `ON_ERROR_RECOVERY`, `ON_LOAD`, `WIFI_ONLY`, `NEVER` • Path: `updates.checkAutomatically`
By default, expo-updates will check for updates every time the app is loaded. Set this to `ON_ERROR_RECOVERY` to disable automatic checking unless recovering from an error. Set this to `NEVER` to disable automatic checking. Valid values: `ON_LOAD` (default value), `ON_ERROR_RECOVERY`, `WIFI_ONLY`, `NEVER`
#### `useEmbeddedUpdate`
Type: `boolean` • Path: `updates.useEmbeddedUpdate`
Whether to load the embedded update. Defaults to true. If set to false, an update will be fetched at launch. When set to false, ensure that `checkAutomatically` is set to `ON_LOAD` and `fallbackToCacheTimeout` is large enough for the initial remote update to download. This should not be used in production.
#### `fallbackToCacheTimeout`
Type: `number` • Path: `updates.fallbackToCacheTimeout`
How long (in ms) to wait for the app to check for and fetch a new update upon launch before falling back to the most recent update already present on the device. Defaults to 0. Must be between 0 and 300000 (5 minutes). If the startup update check takes longer than this value, any update downloaded during the check will be applied upon the next app launch.
#### `url`
Type: `string` • Path: `updates.url`
URL from which expo-updates will fetch update manifests
#### `codeSigningCertificate`
Type: `string` • Path: `updates.codeSigningCertificate`
Local path of a PEM-formatted X.509 certificate used for verifying codesigned updates. When provided, all updates downloaded by expo-updates must be signed.
#### `codeSigningMetadata`
Type: `object` • Path: `updates.codeSigningMetadata`
Metadata for `codeSigningCertificate`
##### `alg`
Type: `enum` • One of: `rsa-v1_5-sha256` • Path: `updates.codeSigningMetadata.alg`
Algorithm used to generate manifest code signing signature. Valid values: `rsa-v1_5-sha256`
##### `keyid`
Type: `string` • Path: `updates.codeSigningMetadata.keyid`
Identifier for the key in the certificate. Used to instruct signing mechanisms when signing or verifying signatures.
#### `requestHeaders`
Type: `object` • Path: `updates.requestHeaders`
Extra HTTP headers to include in HTTP requests made by `expo-updates` when fetching manifests or assets. These may override preset headers.
#### `assetPatternsToBeBundled`
Type: `array` • Path: `updates.assetPatternsToBeBundled`
Array of glob patterns specifying which files should be included in updates. Glob patterns are relative to the project root. A value of `['**']` will match all asset files within the project root. When not supplied all asset files will be included. Example: Given a value of `['app/images/**/*.png', 'app/fonts/**/*.woff']` all `.png` files in all subdirectories of `app/images` and all `.woff` files in all subdirectories of `app/fonts` will be included in updates.
#### `disableAntiBrickingMeasures`
Type: `boolean` • Path: `updates.disableAntiBrickingMeasures`
Whether to disable the built-in expo-updates anti-bricking measures. Defaults to false. If set to true, this will allow overriding certain configuration options from the JS API, which is liable to leave an app in a bricked state if not done carefully. This should not be used in production.
#### `useNativeDebug`
Type: `boolean` • Path: `updates.useNativeDebug`
Enable debugging of native code with updates enabled. Defaults to false. If set to true, the EX_UPDATES_NATIVE_DEBUG environment variable will be set in Podfile.properties.json and gradle.properties. This causes Xcode and Android Studio debug builds to be built with expo-updates enabled, and JS debugging (with dev client or packager) disabled. This should not be used in production.
#### `enableBsdiffPatchSupport`
Type: `boolean` • Path: `updates.enableBsdiffPatchSupport`
Whether to enable support for downloading and applying bundle diffs using bsdiff. Defaults to false.
### `locales`
Type: `object`
Provide per-locale values for System Dialog prompts such as Permissions Boxes, and create Localizable.strings file to localize (for example) push notifications. Platform-specific locale strings should be nested under `ios` and `android` keys.
Existing React Native app?
To add or change language and localization information in your iOS app, you need to use Xcode.
### `plugins`
Type: `array`
Config plugins for adding extra functionality to your project. [Learn more](https://docs.expo.dev/guides/config-plugins/).
Existing React Native app?
Plugins that add modifications can only be used with [prebuilding](https://expo.fyi/prebuilding) and managed EAS Build
### `buildCacheProvider`
Type: `undefined`
Enable downloading cached builds from remote.
### `ios`
Type: `object`
Configuration that is specific to the iOS platform.
#### `appleTeamId`
Type: `string` • Path: `ios.appleTeamId`
The Apple development team ID to use for all native targets. You can find your team ID in [the Apple Developer Portal](https://developer.apple.com/help/account/manage-your-team/locate-your-team-id/).
#### `publishManifestPath`
Type: `string` • Path: `ios.publishManifestPath`
The manifest for the iOS version of your app will be written to this path during publish.
#### `publishBundlePath`
Type: `string` • Path: `ios.publishBundlePath`
The bundle for the iOS version of your app will be written to this path during publish.
#### `bundleIdentifier`
Type: `string` • Path: `ios.bundleIdentifier`
The bundle identifier for your iOS standalone app. You make it up, but it needs to be unique on the App Store. See [this StackOverflow question](http://stackoverflow.com/questions/11347470/what-does-bundle-identifier-mean-in-the-ios-project).
iOS bundle identifier notation unique name for your app. For example, `host.exp.expo`, where `exp.host` is our domain and `expo` is our app name.
Existing React Native app?
Set this value in `info.plist` under `CFBundleIdentifier`
#### `buildNumber`
Type: `string` • Path: `ios.buildNumber`
Build number for your iOS standalone app. Corresponds to `CFBundleVersion` and must match Apple's [specified format](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleversion). (Note: Transporter will pull the value for `Version Number` from `expo.version` and NOT from `expo.ios.buildNumber`.)
Existing React Native app?
Set this value in `info.plist` under `CFBundleVersion`
#### `backgroundColor`
Type: `string` • Path: `ios.backgroundColor`
The background color for your iOS app, behind any of your React views. Overrides the top-level `backgroundColor` key if it is present. Requires `expo-system-ui` be installed in your project to work on iOS.
6 character long hex color string, for example, `'#000000'`
#### `scheme`
One of types:
- `string` matching the following pattern: `^[a-z][a-z0-9+.-]*$`
`{ "type": "array", "items": { "type": "string", "pattern": "^[a-z][a-z0-9+.-]*$" } }`
URL scheme(s) to link into your iOS app. Schemes added to this field will be merged with the schemes in the `scheme` key at the top level of the config.
String beginning with a **lowercase** letter followed by any combination of **lowercase** letters, digits, "+", "." or "-"
Existing React Native app?
To change your app's scheme, replace all occurrences of the old scheme in `Info.plist` and `AndroidManifest.xml`
#### `icon`
One of types:
- `string` matching the following pattern: `\.icon$`
- `string`
- An `object` with the following properties:
##### `light`
Type: `string` • Path: `ios.icon.light`
The light icon. It will appear when neither dark nor tinted icons are used, or if they are not provided.
##### `dark`
Type: `string` • Path: `ios.icon.dark`
The dark icon. It will appear for the app when the user's system appearance is dark. See Apple's [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/app-icons#iOS-iPadOS) for more information.
##### `tinted`
Type: `string` • Path: `ios.icon.tinted`
The tinted icon. It will appear for the app when the user's system appearance is tinted. See Apple's [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/app-icons#iOS-iPadOS) for more information.
Local path or remote URL to an image to use for your app's icon on iOS. Alternatively, an object specifying different icons for various system appearances (e.g., dark, tinted) can be provided. You can also provide a path to a .icon directory. If specified, this overrides the top-level `icon` key. Use a 1024x1024 icon which follows Apple's interface guidelines for icons, including color profile and transparency.
Expo will generate the other required sizes. This icon will appear on the home screen and within the Expo Go app.
#### `appStoreUrl`
Type: `string` • Path: `ios.appStoreUrl`
URL to your app on the Apple App Store, if you have deployed it there. This is used to link to your store page from your Expo project page if your app is public.
Example
`"https://apps.apple.com/us/app/expo-client/id982107779"`
#### `bitcode`
Type: `undefined` • Path: `ios.bitcode`
Enable iOS Bitcode optimizations in the native build. Accepts the name of an iOS build configuration to enable for a single configuration and disable for all others, e.g. Debug, Release. Not available in Expo Go. Defaults to `undefined` which uses the template's predefined settings.
#### `config`
Type: `object` • Path: `ios.config`
Note: This property key is not included in the production manifest and will evaluate to `undefined`. It is used internally only in the build process, because it contains API keys that some may want to keep private.
##### `branch`
Type: `object` • Path: `ios.config.branch`
[Branch](https://branch.io/) key to hook up Branch linking services.
##### `apiKey`
Type: `string` • Path: `ios.config.branch.apiKey`
Your Branch API key
##### `usesNonExemptEncryption`
Type: `boolean` • Path: `ios.config.usesNonExemptEncryption`
Sets `ITSAppUsesNonExemptEncryption` in the standalone ipa's Info.plist to the given boolean value.
##### `googleMapsApiKey`
Type: `string` • Path: `ios.config.googleMapsApiKey`
[Google Maps iOS SDK](https://developers.google.com/maps/documentation/ios-sdk/start) key for your standalone app.
##### `googleMobileAdsAppId`
> Deprecated
Type: `string` • Path: `ios.config.googleMobileAdsAppId`
This field was used by the `expo-ads-admob` package, which has been deprecated and removed. [Google Mobile Ads App ID](https://support.google.com/admob/answer/6232340) Google AdMob App ID.
##### `googleMobileAdsAutoInit`
> Deprecated
Type: `boolean` • Path: `ios.config.googleMobileAdsAutoInit`
This field was used by the `expo-ads-admob` package, which has been deprecated and removed. A boolean indicating whether to initialize Google App Measurement and begin sending user-level event data to Google immediately when the app starts. The default in Expo (Go and in standalone apps) is `false`. [Sets the opposite of the given value to the following key in `Info.plist`.](https://developers.google.com/admob/ios/eu-consent#delay_app_measurement_optional)
#### `googleServicesFile`
Type: `string` • Path: `ios.googleServicesFile`
[Firebase Configuration File](https://support.google.com/firebase/answer/7015592) Location of the `GoogleService-Info.plist` file for configuring Firebase.
#### `supportsTablet`
Type: `boolean` • Path: `ios.supportsTablet`
Whether your standalone iOS app supports tablet screen sizes. Defaults to `false`.
Existing React Native app?
Set this value in `info.plist` under `UISupportedInterfaceOrientations~ipad`
#### `isTabletOnly`
Type: `boolean` • Path: `ios.isTabletOnly`
If true, indicates that your standalone iOS app does not support handsets, and only supports tablets.
Existing React Native app?
Set this value in `info.plist` under `UISupportedInterfaceOrientations`
#### `requireFullScreen`
Type: `boolean` • Path: `ios.requireFullScreen`
If true, indicates that your standalone iOS app does not support Slide Over and Split View on iPad. Defaults to `false`
Existing React Native app?
Use Xcode to set `UIRequiresFullScreen`
#### `userInterfaceStyle`
Type: `enum` • One of: `light`, `dark`, `automatic` • Path: `ios.userInterfaceStyle`
Configuration to force the app to always use the light or dark user-interface appearance, such as "dark mode", or make it automatically adapt to the system preferences. If not provided, defaults to `light`.
#### `infoPlist`
Type: `object` • Path: `ios.infoPlist`
Dictionary of arbitrary configuration to add to your standalone app's native Info.plist. Applied prior to all other Expo-specific configuration. No other validation is performed, so use this at your own risk of rejection from the App Store.
#### `entitlements`
Type: `object` • Path: `ios.entitlements`
Dictionary of arbitrary configuration to add to your standalone app's native \*.entitlements (plist). Applied prior to all other Expo-specific configuration. No other validation is performed, so use this at your own risk of rejection from the App Store.
#### `privacyManifests`
Type: `object` • Path: `ios.privacyManifests`
Dictionary of privacy manifest definitions to add to your app's native PrivacyInfo.xcprivacy file. [Learn more](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files)
##### `NSPrivacyAccessedAPITypes`
Type: `array` • Path: `ios.privacyManifests.NSPrivacyAccessedAPITypes`
A list of required reasons of why your app uses restricted API categories. [Learn more](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api)
##### `NSPrivacyAccessedAPIType`
Type: `string` • Path: `ios.privacyManifests.NSPrivacyAccessedAPITypes.NSPrivacyAccessedAPIType`
A string that identifies the category of required reason APIs your app uses
##### `NSPrivacyAccessedAPITypeReasons`
Type: `array` • Path: `ios.privacyManifests.NSPrivacyAccessedAPITypes.NSPrivacyAccessedAPITypeReasons`
A list of reasons for a specific category.
##### `NSPrivacyTrackingDomains`
Type: `array` • Path: `ios.privacyManifests.NSPrivacyTrackingDomains`
A list of domains that your app uses for tracking.
##### `NSPrivacyTracking`
Type: `boolean` • Path: `ios.privacyManifests.NSPrivacyTracking`
A Boolean that indicates whether your app or third-party SDK uses data for tracking.
##### `NSPrivacyCollectedDataTypes`
Type: `array` • Path: `ios.privacyManifests.NSPrivacyCollectedDataTypes`
A list of collected data types that your app uses.
##### `NSPrivacyCollectedDataType`
Type: `string` • Path: `ios.privacyManifests.NSPrivacyCollectedDataTypes.NSPrivacyCollectedDataType`
##### `NSPrivacyCollectedDataTypeLinked`
Type: `boolean` • Path: `ios.privacyManifests.NSPrivacyCollectedDataTypes.NSPrivacyCollectedDataTypeLinked`
##### `NSPrivacyCollectedDataTypeTracking`
Type: `boolean` • Path: `ios.privacyManifests.NSPrivacyCollectedDataTypes.NSPrivacyCollectedDataTypeTracking`
##### `NSPrivacyCollectedDataTypePurposes`
Type: `array` • Path: `ios.privacyManifests.NSPrivacyCollectedDataTypes.NSPrivacyCollectedDataTypePurposes`
#### `associatedDomains`
Type: `array` • Path: `ios.associatedDomains`
An array that contains Associated Domains for the standalone app. [Learn more](https://developer.apple.com/documentation/safariservices/supporting_associated_domains).
Entries must follow the format `applinks:[:port number]`. [Learn more](https://developer.apple.com/documentation/safariservices/supporting_associated_domains).
Existing React Native app?
Build with EAS, or use Xcode to enable this capability manually. [Learn more](https://developer.apple.com/documentation/safariservices/supporting_associated_domains).
#### `usesIcloudStorage`
Type: `boolean` • Path: `ios.usesIcloudStorage`
A boolean indicating if the app uses iCloud Storage for `DocumentPicker`. See `DocumentPicker` docs for details.
Existing React Native app?
Use Xcode, or ios.entitlements to configure this.
#### `usesAppleSignIn`
Type: `boolean` • Path: `ios.usesAppleSignIn`
A boolean indicating if the app uses Apple Sign-In. See `AppleAuthentication` docs for details.
#### `usesBroadcastPushNotifications`
Type: `boolean` • Path: `ios.usesBroadcastPushNotifications`
A boolean indicating if the app uses Push Notifications Broadcast option for Push Notifications capability. If true, EAS CLI will use the value during capability syncing. If EAS CLI is not used, this configuration will not have any effect unless another tool is used to operate on it, so enable the capability manually on the Apple Developer Portal in that case.
#### `accessesContactNotes`
Type: `boolean` • Path: `ios.accessesContactNotes`
A Boolean value that indicates whether the app may access the notes stored in contacts. You must [receive permission from Apple](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_contacts_notes) before you can submit your app for review with this capability.
#### `splash`
> Deprecated
Type: `object` • Path: `ios.splash`
Use the `expo-splash-screen` config plugin instead. Configuration for loading and splash screen for standalone iOS apps.
##### `backgroundColor`
Type: `string` • Path: `ios.splash.backgroundColor`
Color to fill the loading screen background
6 character long hex color string, for example, `'#000000'`
##### `resizeMode`
Type: `enum` • One of: `cover`, `contain` • Path: `ios.splash.resizeMode`
Determines how the `image` will be displayed in the splash loading screen. Must be one of `cover` or `contain`, defaults to `contain`.
##### `image`
Type: `string` • Path: `ios.splash.image`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
##### `tabletImage`
Type: `string` • Path: `ios.splash.tabletImage`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
##### `dark`
Type: `object` • Path: `ios.splash.dark`
Configuration for loading and splash screen for standalone iOS apps in dark mode.
##### `backgroundColor`
Type: `string` • Path: `ios.splash.dark.backgroundColor`
Color to fill the loading screen background
6 character long hex color string, for example, `'#000000'`
##### `resizeMode`
Type: `enum` • One of: `cover`, `contain` • Path: `ios.splash.dark.resizeMode`
Determines how the `image` will be displayed in the splash loading screen. Must be one of `cover` or `contain`, defaults to `contain`.
##### `image`
Type: `string` • Path: `ios.splash.dark.image`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
##### `tabletImage`
Type: `string` • Path: `ios.splash.dark.tabletImage`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
#### `runtimeVersion`
One of types:
- `string` matching the following pattern: `^[a-zA-Z\d][a-zA-Z\d._+()-]{0,254}$`
- `string` matching the following pattern: `^exposdk:((\d+\.\d+\.\d+)|(UNVERSIONED))$`
- An `object` with the following properties:
##### `policy`
Type: `enum` • Path: `ios.runtimeVersion.policy`
Valid values: `nativeVersion`, `sdkVersion`, `appVersion`, `fingerprint`.
Property indicating compatibility between an iOS build's native code and an OTA update for the iOS platform. If provided, this will override the value of the top level `runtimeVersion` key on iOS.
#### `version`
Type: `string` • Path: `ios.version`
Your iOS app version. Takes precedence over the root `version` field. In addition to this field, you'll also use `ios.buildNumber` — read more about how to version your app [here](https://docs.expo.dev/distribution/app-stores/#versioning-your-app). This corresponds to `CFBundleShortVersionString`. The required format can be found [here](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring).
Existing React Native app?
To change your app version, edit the 'Version' field in Xcode\`
### `android`
Type: `object`
Configuration that is specific to the Android platform.
#### `publishManifestPath`
Type: `string` • Path: `android.publishManifestPath`
The manifest for the Android version of your app will be written to this path during publish.
#### `publishBundlePath`
Type: `string` • Path: `android.publishBundlePath`
The bundle for the Android version of your app will be written to this path during publish.
#### `package`
Type: `string` • Path: `android.package`
The package name for your Android standalone app. You make it up, but it needs to be unique on the Play Store. See [this StackOverflow question](http://stackoverflow.com/questions/6273892/android-package-name-convention).
Reverse DNS notation unique name for your app. Valid Android Application ID. For example, `com.example.app`, where `com.example` is our domain and `app` is our app. The name may only contain lowercase and uppercase letters (a-z, A-Z), numbers (0-9) and underscores (_), separated by periods (.). Each component of the name should start with a lowercase letter.
Existing React Native app?
This is set in `android/app/build.gradle` as `applicationId` as well as in your `AndroidManifest.xml` file (multiple places).
#### `versionCode`
Type: `integer` • Path: `android.versionCode`
Version number required by Google Play. Increment by one for each release. Must be a positive integer. [Learn more](https://developer.android.com/studio/publish/versioning.html)
Existing React Native app?
This is set in `android/app/build.gradle` as `versionCode`
#### `backgroundColor`
Type: `string` • Path: `android.backgroundColor`
The background color for your Android app, behind any of your React views. Overrides the top-level `backgroundColor` key if it is present.
6 character long hex color string, for example, `'#000000'`
Existing React Native app?
This is set in `android/app/src/main/AndroidManifest.xml` under `android:windowBackground`
#### `userInterfaceStyle`
Type: `enum` • One of: `light`, `dark`, `automatic` • Path: `android.userInterfaceStyle`
Configuration to force the app to always use the light or dark user-interface appearance, such as "dark mode", or make it automatically adapt to the system preferences. If not provided, defaults to `light`. Requires `expo-system-ui` be installed in your project to work on Android.
#### `scheme`
One of types:
- `string` matching the following pattern: `^[a-z][a-z0-9+.-]*$`
`{ "type": "array", "items": { "type": "string", "pattern": "^[a-z][a-z0-9+.-]*$" } }`
URL scheme(s) to link into your Android app. Schemes added to this field will be merged with the schemes in the `scheme` key at the top level of the config.
String beginning with a **lowercase** letter followed by any combination of **lowercase** letters, digits, "+", "." or "-"
Existing React Native app?
To change your app's scheme, replace all occurrences of the old scheme in `Info.plist` and `AndroidManifest.xml`
#### `icon`
Type: `string` • Path: `android.icon`
Local path or remote URL to an image to use for your app's icon on Android. If specified, this overrides the top-level `icon` key. We recommend that you use a 1024x1024 png file (transparency is recommended for the Google Play Store). This icon will appear on the home screen and within the Expo Go app.
#### `adaptiveIcon`
Type: `object` • Path: `android.adaptiveIcon`
Settings for an Adaptive Launcher Icon on Android. [Learn more](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive)
##### `foregroundImage`
Type: `string` • Path: `android.adaptiveIcon.foregroundImage`
Local path or remote URL to an image to use for your app's icon on Android. If specified, this overrides the top-level `icon` and the `android.icon` keys. Should follow the [specified guidelines](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive). This icon will appear on the home screen.
##### `monochromeImage`
Type: `string` • Path: `android.adaptiveIcon.monochromeImage`
Local path or remote URL to an image representing the Android 13+ monochromatic icon. Should follow the [specified guidelines](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive). This icon will appear on the home screen when the user enables 'Themed icons' in system settings on a device running Android 13+.
##### `backgroundImage`
Type: `string` • Path: `android.adaptiveIcon.backgroundImage`
Local path or remote URL to a background image for your app's Adaptive Icon on Android. If specified, this overrides the `backgroundColor` key. Must have the same dimensions as `foregroundImage`, and has no effect if `foregroundImage` is not specified. Should follow the [specified guidelines](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive).
##### `backgroundColor`
Type: `string` • Path: `android.adaptiveIcon.backgroundColor`
Color to use as the background for your app's Adaptive Icon on Android. Defaults to white, `#FFFFFF`. Has no effect if `foregroundImage` is not specified.
6 character long hex color string, for example, `'#000000'`
#### `playStoreUrl`
Type: `string` • Path: `android.playStoreUrl`
URL to your app on the Google Play Store, if you have deployed it there. This is used to link to your store page from your Expo project page if your app is public.
Example
`"https://play.google.com/store/apps/details?id=host.exp.exponent"`
#### `permissions`
Type: `array` • Path: `android.permissions`
A list of permissions to add to the app `AndroidManifest.xml` during prebuild. For example: `['android.permission.SCHEDULE_EXACT_ALARM']`
Existing React Native app?
To change the permissions your app requests, edit `AndroidManifest.xml` directly. To prevent your app from requesting specific permissions (which may automatically be added through an installed native package), add those permissions to `AndroidManifest.xml` along with a `tools:node="remove"` tag.
#### `blockedPermissions`
Type: `array` • Path: `android.blockedPermissions`
List of permissions to block in the final `AndroidManifest.xml`. This is useful for removing permissions that are added by native package `AndroidManifest.xml` files which are merged into the final manifest. Internally this feature uses the `tools:node="remove"` XML attribute to remove permissions. Not available in Expo Go.
#### `googleServicesFile`
Type: `string` • Path: `android.googleServicesFile`
[Firebase Configuration File](https://support.google.com/firebase/answer/7015592) Location of the `google-services.json` file for configuring Firebase. Including this key automatically enables FCM in your standalone app.
Existing React Native app?
Add or edit the file directly at `android/app/google-services.json`
#### `config`
Type: `object` • Path: `android.config`
Note: This property key is not included in the production manifest and will evaluate to `undefined`. It is used internally only in the build process, because it contains API keys that some may want to keep private.
##### `branch`
Type: `object` • Path: `android.config.branch`
[Branch](https://branch.io/) key to hook up Branch linking services.
##### `apiKey`
Type: `string` • Path: `android.config.branch.apiKey`
Your Branch API key
##### `googleMaps`
Type: `object` • Path: `android.config.googleMaps`
[Google Maps Android SDK](https://developers.google.com/maps/documentation/android-api/signup) configuration for your standalone app.
##### `apiKey`
Type: `string` • Path: `android.config.googleMaps.apiKey`
Your Google Maps Android SDK API key
##### `googleMobileAdsAppId`
> Deprecated
Type: `string` • Path: `android.config.googleMobileAdsAppId`
This field was used by the `expo-ads-admob` package, which has been deprecated and removed. [Google Mobile Ads App ID](https://support.google.com/admob/answer/6232340) Google AdMob App ID.
##### `googleMobileAdsAutoInit`
> Deprecated
Type: `boolean` • Path: `android.config.googleMobileAdsAutoInit`
This field was used by the `expo-ads-admob` package, which has been deprecated and removed. A boolean indicating whether to initialize Google App Measurement and begin sending user-level event data to Google immediately when the app starts. The default in Expo (Client and in standalone apps) is `false`. [Sets the opposite of the given value to the following key in `Info.plist`](https://developers.google.com/admob/ios/eu-consent#delay_app_measurement_optional)
#### `splash`
> Deprecated
Type: `object` • Path: `android.splash`
Use the `expo-splash-screen` config plugin instead. Configuration for loading and splash screen for managed and standalone Android apps.
##### `backgroundColor`
Type: `string` • Path: `android.splash.backgroundColor`
Color to fill the loading screen background
6 character long hex color string, for example, `'#000000'`
##### `resizeMode`
Type: `enum` • One of: `cover`, `contain`, `native` • Path: `android.splash.resizeMode`
Determines how the `image` will be displayed in the splash loading screen. Must be one of `cover`, `contain` or `native`, defaults to `contain`.
##### `image`
Type: `string` • Path: `android.splash.image`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
##### `mdpi`
Type: `string` • Path: `android.splash.mdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Natural sized image (baseline)`
##### `hdpi`
Type: `string` • Path: `android.splash.hdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 1.5x`
##### `xhdpi`
Type: `string` • Path: `android.splash.xhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 2x`
##### `xxhdpi`
Type: `string` • Path: `android.splash.xxhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 3x`
##### `xxxhdpi`
Type: `string` • Path: `android.splash.xxxhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 4x`
##### `dark`
Type: `object` • Path: `android.splash.dark`
Configuration for loading and splash screen for managed and standalone Android apps in dark mode.
##### `backgroundColor`
Type: `string` • Path: `android.splash.dark.backgroundColor`
Color to fill the loading screen background
6 character long hex color string, for example, `'#000000'`
##### `resizeMode`
Type: `enum` • One of: `cover`, `contain`, `native` • Path: `android.splash.dark.resizeMode`
Determines how the `image` will be displayed in the splash loading screen. Must be one of `cover`, `contain` or `native`, defaults to `contain`.
##### `image`
Type: `string` • Path: `android.splash.dark.image`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
##### `mdpi`
Type: `string` • Path: `android.splash.dark.mdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Natural sized image (baseline)`
##### `hdpi`
Type: `string` • Path: `android.splash.dark.hdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 1.5x`
##### `xhdpi`
Type: `string` • Path: `android.splash.dark.xhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 2x`
##### `xxhdpi`
Type: `string` • Path: `android.splash.dark.xxhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 3x`
##### `xxxhdpi`
Type: `string` • Path: `android.splash.dark.xxxhdpi`
Local path or remote URL to an image to fill the background of the loading screen in "native" mode. Image size and aspect ratio are up to you. [Learn more](https://developer.android.com/training/multiscreen/screendensities)
`Scale 4x`
#### `intentFilters`
Type: `array` • Path: `android.intentFilters`
Configuration for setting an array of custom intent filters in Android manifest. [Learn more](https://developer.android.com/guide/components/intents-filters)
Existing React Native app?
This is set in `AndroidManifest.xml` directly. [Learn more.](https://developer.android.com/guide/components/intents-filters)
Example
`[ { "autoVerify": true, "action": "VIEW", "data": { "scheme": "https", "host": "*.example.com" }, "category": [ "BROWSABLE", "DEFAULT" ] } ]`
##### `autoVerify`
Type: `boolean` • Path: `android.intentFilters.autoVerify`
You may also use an intent filter to set your app as the default handler for links (without showing the user a dialog with options). To do so use `true` and then configure your server to serve a JSON file verifying that you own the domain. [Learn more](https://developer.android.com/training/app-links)
##### `action`
Type: `string` • Path: `android.intentFilters.action`
##### `data`
Type: `undefined` • Path: `android.intentFilters.data`
##### `category`
Type: `undefined` • Path: `android.intentFilters.category`
#### `allowBackup`
Type: `boolean` • Path: `android.allowBackup`
Allows your user's app data to be automatically backed up to their Google Drive. If this is set to false, no backup or restore of the application will ever be performed (this is useful if your app deals with sensitive information). Defaults to the Android default, which is `true`.
#### `softwareKeyboardLayoutMode`
Type: `enum` • One of: `resize`, `pan` • Path: `android.softwareKeyboardLayoutMode`
Determines how the software keyboard will impact the layout of your application. This maps to the `android:windowSoftInputMode` property. Defaults to `resize`. Valid values: `resize`, `pan`.
#### `runtimeVersion`
One of types:
- `string` matching the following pattern: `^[a-zA-Z\d][a-zA-Z\d._+()-]{0,254}$`
- `string` matching the following pattern: `^exposdk:((\d+\.\d+\.\d+)|(UNVERSIONED))$`
- An `object` with the following properties:
##### `policy`
Type: `enum` • Path: `android.runtimeVersion.policy`
Valid values: `nativeVersion`, `sdkVersion`, `appVersion`, `fingerprint`.
Property indicating compatibility between a Android build's native code and an OTA update for the Android platform. If provided, this will override the value of top level `runtimeVersion` key on Android.
#### `version`
Type: `string` • Path: `android.version`
Your android app version. Takes precedence over the root `version` field. In addition to this field, you'll also use `android.versionCode` — read more about how to version your app [here](https://docs.expo.dev/distribution/app-stores/#versioning-your-app). This corresponds to `versionName`. The required format can be found [here](https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring).
Existing React Native app?
To change your app version, edit the `versionName` string in `android/app/build.gradle`
#### `predictiveBackGestureEnabled`
Type: `boolean` • Path: `android.predictiveBackGestureEnabled`
Enable your app to use the [predictive back gesture](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) on Android 13 (API level 33) and later. Default to false.
Existing React Native app?
To change the setting, update the `android:enableOnBackInvokedCallback` value in `AndroidManifest.xml`.
### `web`
Type: `object`
Configuration that is specific to the web platform.
#### `output`
Type: `enum` • One of: `single`, `static`, `server` • Path: `web.output`
Sets the export method for the web app for both `expo start` and `expo export`. `static` statically renders HTML files for every route in the `app/` directory, which is available only in Expo Router apps. `single` outputs a Single Page Application (SPA), with a single `index.html` in the output folder, and has no statically indexable HTML. `server` outputs static HTML, and API Routes for hosting with a custom Node.js server. Defaults to `single`.
#### `favicon`
Type: `string` • Path: `web.favicon`
Relative path of an image to use for your app's favicon.
#### `name`
Type: `string` • Path: `web.name`
Defines the title of the document, defaults to the outer level name
#### `shortName`
Type: `string` • Path: `web.shortName`
A short version of the app's name, 12 characters or fewer. Used in app launcher and new tab pages. Maps to `short_name` in the PWA manifest.json. Defaults to the `name` property.
Maximum 12 characters long
#### `lang`
Type: `string` • Path: `web.lang`
Specifies the primary language for the values in the name and short_name members. This value is a string containing a single language tag.
#### `scope`
Type: `string` • Path: `web.scope`
Defines the navigation scope of this website's context. This restricts what web pages can be viewed while the manifest is applied. If the user navigates outside the scope, it returns to a normal web page inside a browser tab/window. If the scope is a relative URL, the base URL will be the URL of the manifest.
#### `themeColor`
Type: `string` • Path: `web.themeColor`
Defines the color of the Android tool bar, and may be reflected in the app's preview in task switchers.
6 character long hex color string, for example, `'#000000'`
#### `description`
Type: `string` • Path: `web.description`
Provides a general description of what the pinned website does.
#### `dir`
Type: `enum` • One of: `auto`, `ltr`, `rtl` • Path: `web.dir`
Specifies the primary text direction for the name, short_name, and description members. Together with the lang member, it helps the correct display of right-to-left languages.
#### `display`
Type: `enum` • One of: `fullscreen`, `standalone`, `minimal-ui`, `browser` • Path: `web.display`
Defines the developers’ preferred display mode for the website.
#### `startUrl`
Type: `string` • Path: `web.startUrl`
The URL that loads when a user launches the application (e.g., when added to home screen), typically the index. Note: This has to be a relative URL, relative to the manifest URL.
#### `orientation`
Type: `enum` • One of: `any`, `natural`, `landscape`, `landscape-primary`, `landscape-secondary`, `portrait`, `portrait-primary`, `portrait-secondary` • Path: `web.orientation`
Defines the default orientation for all the website's top level browsing contexts.
#### `backgroundColor`
Type: `string` • Path: `web.backgroundColor`
Defines the expected “background color” for the website. This value repeats what is already available in the site’s CSS, but can be used by browsers to draw the background color of a shortcut when the manifest is available before the stylesheet has loaded. This creates a smooth transition between launching the web application and loading the site's content.
6 character long hex color string, for example, `'#000000'`
#### `barStyle`
Type: `enum` • One of: `default`, `black`, `black-translucent` • Path: `web.barStyle`
If content is set to default, the status bar appears normal. If set to black, the status bar has a black background. If set to black-translucent, the status bar is black and translucent. If set to default or black, the web content is displayed below the status bar. If set to black-translucent, the web content is displayed on the entire screen, partially obscured by the status bar.
#### `preferRelatedApplications`
Type: `boolean` • Path: `web.preferRelatedApplications`
Hints for the user agent to indicate to the user that the specified native applications (defined in expo.ios and expo.android) are recommended over the website.
#### `dangerous`
Type: `object` • Path: `web.dangerous`
Experimental features. These will break without deprecation notice.
#### `splash`
Type: `object` • Path: `web.splash`
Configuration for PWA splash screens.
Existing React Native app?
Use [expo-splash-screen](https://github.com/expo/expo/tree/main/packages/expo-splash-screen#expo-splash-screen)
##### `backgroundColor`
Type: `string` • Path: `web.splash.backgroundColor`
Color to fill the loading screen background
6 character long hex color string, for example, `'#000000'`
##### `resizeMode`
Type: `enum` • One of: `cover`, `contain` • Path: `web.splash.resizeMode`
Determines how the `image` will be displayed in the splash loading screen. Must be one of `cover` or `contain`, defaults to `contain`.
##### `image`
Type: `string` • Path: `web.splash.image`
Local path or remote URL to an image to fill the background of the loading screen. Image size and aspect ratio are up to you. Must be a .png.
#### `config`
Type: `object` • Path: `web.config`
Firebase web configuration. Used by the expo-firebase packages on both web and native. [Learn more](https://firebase.google.com/docs/reference/js/firebase.html#initializeapp)
##### `firebase`
Type: `object` • Path: `web.config.firebase`
##### `apiKey`
Type: `string` • Path: `web.config.firebase.apiKey`
##### `authDomain`
Type: `string` • Path: `web.config.firebase.authDomain`
##### `databaseURL`
Type: `string` • Path: `web.config.firebase.databaseURL`
##### `projectId`
Type: `string` • Path: `web.config.firebase.projectId`
##### `storageBucket`
Type: `string` • Path: `web.config.firebase.storageBucket`
##### `messagingSenderId`
Type: `string` • Path: `web.config.firebase.messagingSenderId`
##### `appId`
Type: `string` • Path: `web.config.firebase.appId`
##### `measurementId`
Type: `string` • Path: `web.config.firebase.measurementId`
#### `bundler`
Type: `enum` • One of: `webpack`, `metro` • Path: `web.bundler`
Sets the bundler to use for the web platform. Only supported in the local CLI `npx expo`. Defaults to `webpack` if the `@expo/webpack-config` package is installed, if not, it defaults to `metro`.
### `experiments`
Type: `object`
Enable experimental features that may be unstable, unsupported, or removed without deprecation notices.
#### `autolinkingModuleResolution`
Type: `boolean` • Path: `experiments.autolinkingModuleResolution`
Apply Expo Autolinking's search results to Metro's module resolution. This forces your project's dependencies on `react`, `react-dom`, and `react-native`, and the autolinked versions of any Expo and React Native modules to be resolved when bundling your app. This prevents version misalignment and is useful for monorepos and to prevent conflicts.
#### `baseUrl`
Type: `string` • Path: `experiments.baseUrl`
Export a website relative to a subpath of a domain. The path will be prepended as-is to links to all bundled resources. Prefix the path with a `/` (recommended) to load all resources relative to the server root. If the path **does not** start with a `/` then resources will be loaded relative to the code that requests them, this could lead to unexpected behavior. Example '/subpath'. Defaults to '' (empty string).
#### `buildCacheProvider`
> Deprecated
Type: `undefined` • Path: `experiments.buildCacheProvider`
This field is not longer marked as experimental and will be removed in a future release, use the `buildCacheProvider` field instead.
#### `supportsTVOnly`
Type: `boolean` • Path: `experiments.supportsTVOnly`
If true, indicates that this project does not support tablets or handsets, and only supports Apple TV and Android TV
#### `functionalCSS`
Type: `boolean` • Path: `experiments.functionalCSS`
Enable React-based CSS support for native platforms. Only supports a subset of CSS properties, class names selectors, and has no cascading.
#### `tsconfigPaths`
Type: `boolean` • Path: `experiments.tsconfigPaths`
Enable tsconfig/jsconfig `compilerOptions.paths` and `compilerOptions.baseUrl` support for import aliases in Metro.
#### `typedRoutes`
Type: `boolean` • Path: `experiments.typedRoutes`
Enable support for statically typed links in Expo Router. This feature requires TypeScript be set up in your Expo Router v2 project.
#### `turboModules`
Type: `boolean` • Path: `experiments.turboModules`
Enables Turbo Modules, which are a type of native modules that use a different way of communicating between JS and platform code. When installing a Turbo Module you will need to enable this experimental option (the library still needs to be a part of Expo SDK already, like react-native-reanimated v2). Turbo Modules do not support remote debugging and enabling this option will disable remote debugging.
#### `reactCanary`
Type: `boolean` • Path: `experiments.reactCanary`
Experimentally use a vendored canary build of React for testing upcoming features.
#### `reactCompiler`
Type: `boolean` • Path: `experiments.reactCompiler`
Experimentally enable React Compiler.
#### `reactServerComponentRoutes`
Type: `boolean` • Path: `experiments.reactServerComponentRoutes`
Experimentally enable React Server Components by default in Expo Router and concurrent routing for transitions.
#### `reactServerFunctions`
Type: `boolean` • Path: `experiments.reactServerFunctions`
Experimentally enable React Server Functions support in Expo CLI and Expo Router.
### `_internal`
Type: `object`
Internal properties for developer tools
#### `pluginHistory`
Type: `object` • Path: `_internal.pluginHistory`
List of plugins already run on the config
---
---
title: babel.config.js
description: Babel 配置文件参考。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/config/babel/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# babel.config.js
Babel 配置文件参考。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
Babel 用作 JavaScript 编译器,将现代 JavaScript(ES6+)转换为与移动设备上的 JavaScript 引擎兼容的版本。
使用 `npx create-expo-app` 创建的每个新 Expo 项目都会自动配置 Babel,并使用 [`babel-preset-expo`](https://github.com/expo/expo/tree/main/packages/babel-preset-expo) 作为默认预设。除非你需要自定义 Babel 配置,否则无需创建 **babel.config.js** 文件。
## 创建 babel.config.js
如果你的项目需要自定义 Babel 配置,你需要按照以下步骤在项目中创建 **babel.config.js** 文件:
1. 导航到项目根目录,并在终端中运行以下命令。这将会在项目根目录生成一个 **babel.config.js** 文件。
```sh
npx expo customize babel.config.js
```
2. **babel.config.js** 文件包含以下默认配置:
```js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
```
3. 如果你对 **babel.config.js** 文件进行了更改,你需要重启 Metro 打包器以应用这些更改,并在 Expo CLI 中使用 `--clear` 选项来清除 Metro 打包器缓存:
```sh
npx expo start --clear
```
## babel-preset-expo
[`babel-preset-expo`](https://github.com/expo/expo/tree/main/packages/babel-preset-expo) 是 Expo 项目中使用的默认预设。它扩展了默认的 React Native 预设(`@react-native/babel-preset`),并增加了对装饰器、Web 库的 tree-shaking 以及加载字体图标的支持。
---
---
title: metro.config.js
description: Metro 中可用配置的参考。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/config/metro/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# metro.config.js
Metro 中可用配置的参考。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
查看更多关于 **metro.config.js** 的信息,请参阅 [自定义 Metro 指南](/guides/customizing-metro)。
## 环境变量
Expo CLI 可以从 **.env** 文件中加载环境变量。有关如何在 Expo CLI 中使用环境变量的更多信息,请参阅 [环境变量指南](/guides/environment-variables)。
EAS CLI 对环境变量使用不同的机制,除非它在编译和打包时调用 Expo CLI。了解更多关于 [EAS 中的环境变量](/eas/environment-variables)。
如果你正在迁移一个较旧的项目,那么你应该通过在 **.gitignore** 中添加以下内容来忽略本地 env 文件:
```sh
# 本地 env 文件
.env*.local
```
### 禁用 dotenv 文件
可以在调用任何 Expo CLI 命令之前,通过启用 `EXPO_NO_DOTENV` 环境变量,来完全禁用 Expo CLI 加载 dotenv 文件。
```sh
npx cross-env EXPO_NO_DOTENV=1 expo start
EXPO_NO_DOTENV=1 npx expo start
```
### 禁用以 `EXPO_PUBLIC_` 为前缀的客户端环境变量
以 `EXPO_PUBLIC_` 为前缀的环境变量会在构建时暴露给应用。例如,`EXPO_PUBLIC_API_KEY` 将可作为 `process.env.EXPO_PUBLIC_API_KEY` 使用。
可以使用环境变量 `EXPO_NO_CLIENT_ENV_VARS=1` 来禁用客户端环境变量内联,这必须在进行任何打包之前定义。
```sh
npx cross-env EXPO_NO_CLIENT_ENV_VARS=1 expo start
EXPO_NO_CLIENT_ENV_VARS=1 npx expo start
```
## CSS
> **信息** CSS 支持仍在开发中,目前仅适用于 web。
Expo 支持你项目中的 CSS。你可以从任何组件中导入 CSS 文件。CSS Modules 也受支持。
CSS 支持默认启用。你可以通过在 Metro 配置中设置 `isCSSEnabled` 来禁用该功能。
```js
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname, {
// 禁用 CSS 支持。
isCSSEnabled: false,
});
```
### 全局 CSS
> **警告** 全局样式仅限 web 使用,使用它会导致你的应用在原生平台上的视觉表现发生偏差。
你可以从任何组件导入一个 CSS 文件。该 CSS 将应用到整个页面。
这里,我们将为类名 `.container` 定义一个全局样式:
```css
.container {
background-color: red;
}
```
然后我们可以通过导入样式表并使用 `.container` 来在组件中使用这个类名:
```jsx
import './styles.css';
import { View } from 'react-native';
export default function App() {
return (
<>
{/* 使用 `className` 为 React DOM 组件分配样式。 */}
>
);
}
```
```css
.text {
color: red;
}
```
- 在 web 上,所有 CSS 值都可用。CSS 不会像 React Native Web 的 `StyleSheet` API 那样被处理或自动添加前缀。你可以使用 `postcss.config.js` 为你的 CSS 自动添加前缀。
- CSS Modules 底层使用 [lightningcss](https://github.com/parcel-bundler/lightningcss),请查看 [这些 issue](https://github.com/parcel-bundler/lightningcss/issues) 了解不受支持的功能。
### PostCSS
可以通过在项目根目录添加 `postcss.config.json` 文件来自定义 [PostCSS](https://github.com/postcss/postcss)。该文件应导出一个返回 PostCSS 配置对象的函数。例如:
```json
{
"plugins": {
"tailwindcss": {}
}
}
```
`postcss.config.json` 和 `postcss.config.js` 都受支持,但 `postcss.config.json` 可以实现更好的缓存。
Expo CLI 会借助对 [browserslist](https://browsersl.ist/) 的内置支持,自动处理 CSS 厂商前缀。请避免添加 `autoprefixer`,因为这会重复该功能并减慢打包速度。
#### 更新后重置缓存
更改 Post CSS 或 `browserslist` 配置后,需要清除 Metro 缓存:
```sh
npx expo start --clear
npx expo export --clear
```
### browserslist
Expo 通过基于 Rust 的 CSS 解析器自动支持 [browserslist](https://browsersl.ist/)。你可以通过在 **package.json** 文件中添加 **browserslist** 字段来自定义 CSS 厂商前缀和浏览器支持。例如:
```json
{
"browserslist": [">0.2%", "not dead", "not op_mini all"]
}
```
### SASS
Expo Metro 对 SCSS/SASS 提供 _部分_ 支持。
要进行设置,请在项目中安装 `sass` 包:
```sh
yarn add -D sass
```
然后,确保在 **metro.config.js** 文件中已完成 [CSS 设置](/versions/latest/config/metro#css)。
- 当安装了 `sass` 时,不带扩展名的模块将按以下顺序解析:`scss`、`sass`、`css`。
- 仅在 `sass` 文件中使用预期的语法。
- 当前不支持从 scss/sass 文件内部导入其他文件。
### Tailwind
> **信息** 标准 Tailwind CSS 仅支持 web 平台。若要获得通用支持,请使用类似 [NativeWind](https://www.nativewind.dev/) 或 [Uniwind](https://uniwind.dev/) 的库,它们允许使用 Tailwind CSS 创建带样式的 React Native 组件。
[Tailwind CSS](/guides/tailwind) — 了解如何在你的 Expo 项目中配置和使用 Tailwind CSS。
## 扩展 Babel 转换器
Expo 的 Metro 配置使用自定义的 `transformer.babelTransformerPath` 值,以确保始终使用 `expo-babel-preset` 并支持 web/Node.js 环境。
如果你想扩展 Babel 转换器,请从 `@expo/metro-config/babel-transformer` 导入上游转换器,而不是 `metro-react-native-babel-transformer`。例如:
```js
const upstreamTransformer = require('@expo/metro-config/babel-transformer');
module.exports.transform = async ({ src, filename, options }) => {
// 对 SVG 文件执行一些自定义处理...
if (filename.endsWith('.svg')) {
src = '...';
}
// 将源代码传递给上游 Expo 转换器。
return upstreamTransformer.transform({ src, filename, options });
};
```
## 自定义解析
Expo CLI 扩展了默认的 Metro 解析器,以添加 Web、Server 和 tsconfig 别名支持等功能。你也可以通过链式调用 `config.resolver.resolveRequest` 函数来类似地自定义 Metro 的默认解析行为。
```tsx
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (moduleName.startsWith('my-custom-resolver:')) {
// 将模块名解析为文件路径的逻辑...
// 注意:如果无法解析,请抛出错误。
return {
filePath: 'path/to/file',
type: 'sourceFile',
};
}
// 确保你调用默认解析器。
return context.resolveRequest(context, moduleName, platform);
};
module.exports = config;
```
与传统打包器不同,Metro 在所有平台上共享同一个解析器函数。因此,你可以使用 `context` 对象在每次请求时动态修改解析设置。
### 模拟模块
如果你希望某个平台上的某个模块为空,可以从解析器返回 `type: 'empty'` 对象。下面的示例会使 `lodash` 在 web 上为空:
```ts
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (platform === 'web' && moduleName === 'lodash') {
return {
type: 'empty',
};
}
// 确保你调用默认解析器。
return context.resolveRequest(context, moduleName, platform);
};
module.exports = config;
```
这种技术等同于在 Webpack 或 Vite 中使用空外部依赖,但额外的好处是可以针对特定平台。
### 虚拟模块
Metro 目前不支持虚拟模块。你可以使用的一种类似方式,是在 `node_modules/.cache/...` 目录中创建一个模块,并将解析重定向到该文件。
下面的示例会在 `node_modules/.cache/virtual/virtual-module.js` 中创建一个模块,并将 `virtual:my-module` 的解析重定向到该文件:
```ts
const path = require('path');
const fs = require('fs');
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
const virtualPath = path.resolve(__dirname, 'node_modules/.cache/virtual/virtual-module.js');
// 在生成目录中创建虚拟模块...
fs.mkdirSync(path.dirname(virtualPath), { recursive: true });
fs.writeFileSync(virtualPath, 'export default "Hello World";');
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (moduleName === 'virtual:my-module') {
return {
filePath: virtualPath,
type: 'sourceFile',
};
}
// 确保你调用默认解析器。
return context.resolveRequest(context, moduleName, platform);
};
module.exports = config;
```
这可用于通过自定义导入来模拟 `externals`。例如,如果你想将 `require('expo')` 重定向到类似 `SystemJS.require('expo')` 的自定义内容,你可以创建一个导出 `SystemJS.require('expo')` 的虚拟模块,并将 `expo` 的解析重定向到该文件。
## 自定义转换
> 转换在 Metro 中有大量缓存。如果你更新了某些内容,请使用 `--clear` 标志查看更新。例如,`npx expo start --clear`。
Metro 没有非常强大的用于转换文件的插件系统,因此改为使用 [**babel.config.js**](/versions/latest/config/babel) 和 caller 对象来自定义转换。
```js
module.exports = function (api) {
// 获取 Expo CLI 正在为其转换的平台。
const platform = api.caller(caller => (caller ? caller.platform : 'ios'));
// 检测打包操作是否用于 Hermes 引擎,例如 `'hermes'` | `undefined`。
const engine = api.caller(caller => (caller ? caller.engine : null));
// 是否为服务器环境进行打包,例如 API Routes。
const isServer = api.caller(caller => (caller ? caller.isServer : false));
// 是否为开发或生产环境进行打包。
const isDev = api.caller(caller =>
caller
? caller.isDev
: process.env.BABEL_ENV === 'development' || process.env.NODE_ENV === 'development'
);
// 确保配置不会被缓存,否则平台将不会更新。
api.cache(false);
// 你也可以提供一种更健壮的 CONFIG 缓存失效方式:
// api.cache.invalidate(() => platform);
return {
presets: ['babel-preset-expo'],
plugins: [
// 基于平台添加一个插件...
platform === 'web' && 'my-plugin',
// 确保过滤掉假值。
].filter(Boolean),
};
};
```
如果 caller 没有 `engine`、`platform`、`bundler` 等信息,那么请确保你使用的是用于 transformer 的 `@expo/metro-config/babel-transformer`。如果你使用的是自定义 transformer,那么它可能需要扩展 Expo transformer。
如果可能,请始终尝试在 resolver 中实现自定义逻辑,因为缓存会简单得多,也更容易理解。例如,如果你需要重映射一个 import,那么使用 resolver 将其解析到一个静态文件,比解析所有可能的导入方式并用 transformer 重新映射它们更简单也更快。
始终使用 `babel-preset-expo` 作为默认的 Babel preset,这可确保转换始终与 Expo 运行时兼容。`babel-preset-expo` 会在内部使用所有 caller 输入,以便针对给定的平台、引擎和环境进行优化。
## Node.js 内置模块
当为服务器环境打包时,Expo 的 Metro 配置会根据当前 Node.js 版本自动支持将 Node.js 内置模块(`fs`、`path`、`node:crypto` 等)外部化。如果 CLI 正在为浏览器环境打包,那么内置模块会先检查该模块是否已在本地安装,然后回退到一个空的 shim。例如,如果你安装了用于浏览器中的 `path`,则可以使用它;否则,该模块会自动被跳过。
## 环境设置
> 这些环境变量不会在测试环境中定义。
Expo 的 Metro 配置会注入构建设置,这些设置可以通过环境变量在客户端 bundle 中使用。所有变量都会被内联,不能动态使用。例如,`process.env["EXPO_BASE_URL"]` 将不起作用。
- `process.env.EXPO_BASE_URL` 会暴露在 `experiments.baseUrl` 中定义的基础 URL。这在 Expo Router 中用于在部署时遵守生产环境的基础 URL。
## Bundle 拆分
Expo CLI 会在生产环境中根据异步导入自动将 web bundle 拆分为多个 chunk。此功能要求安装 `@expo/metro-runtime`,并且在入口 bundle 的某处被导入(在 Expo Router 中默认可用)。
异步 bundle 的共享依赖会合并到单个 chunk 中,以减少请求次数。例如,如果你有两个异步 bundle 都导入了 `lodash`,那么该库会被合并到一个初始 chunk 中。
chunk 拆分的启发式规则无法自定义。例如:
`math.js`
`index.js`
```js
export function add(a, b) {
return a + b;
}
```
```js
import '@expo/metro-runtime';
// 这将被拆分到一个单独的 chunk 中。
import('./math').then(math => {
console.log(math.add(1, 2));
});
```
当你运行 `npx expo export -p web` 时,bundle 会被拆分为多个文件,入口 bundle 会被添加到主 HTML 文件中。`@expo/metro-runtime` 会添加用于加载并执行异步 bundle 的运行时代码。
## Source map debug ID
如果一个 bundle 导出时带有外部 source map,那么会在文件末尾添加一个 [**Debug ID**](https://sentry.engineering/blog/the-case-for-debug-ids) 注解,并在 source map 中添加匹配的 `debugId`,以便将这些文件对应起来。如果未导出 source map,或者使用的是内联 source map,则不会添加该注解。
```js
// <所有源代码>
//# debugId=
```
相关联的 `*.js.map` 或 `*.hbc.map` source map 会是一个 JSON 文件,其中包含等效的 `debugId` 属性。`debugId` 会在 hermes 字节码生成之前注入,以确保在所有情况下都能匹配。
`debugId` 是 bundle 内容的确定性哈希,但不包含外部 bundle 拆分引用。这与用于创建 chunk 文件名的值相同,只是格式化为 UUID。例如,`431b98e2-c997-4975-a3d9-2987710abd44`。
`@expo/metro-config` 会在 `npx expo export` 和 `npx expo export:embed` 期间注入 `debugId`。`npx expo export:embed` 中的任何额外优化步骤,例如 Hermes 字节码生成,都需要手动注入 `debugId`。
## Metro require 运行时
你可以通过环境变量 `EXPO_USE_METRO_REQUIRE=1` 可选地启用自定义 Metro `require` 实现。该运行时具有以下特性:
- 使用人类可读的字符串模块 ID,使缺失模块错误更容易追踪。
- 具有确定性 ID,在多次运行之间以及跨模块都保持一致(开发环境中的 React Server Components 需要此特性)。
- 移除了对旧版 RAM bundle 的支持。
## Magic import 注释
> 从 SDK 52 起在所有平台可用。
诸如 Workers 和 Node.js 等服务器环境支持在运行时导入任意文件,因此你可能希望保持 `import` 语法不变,而不是使用 Metro 的 require 系统。你可以在 `import()` 语句中使用 `/* @metro-ignore */` 注释来选择不使用动态导入。
```js
// 手动确保 `./my-module.js` 被包含在相对于模块的正确位置。
const myModule = await import(/* @metro-ignore */ './my-module.js');
```
Expo CLI 会跳过 `./my-module.js` 依赖,并假定开发者已将其手动添加到输出 bundle 中。在内部,这用于导出自定义服务器代码,该代码会根据请求在文件之间动态切换。避免在原生 bundle 中使用此语法,因为在启用 Hermes 的 React Native 中通常无法使用 `import()`。
许多 React 库都提供了 Webpack 的 `/* webpackIgnore: true */` 注释来实现类似行为。为了弥合差异,我们也添加了对 Webpack 注释的支持,但建议你在应用中使用 Metro 对应的写法。
## ES 模块解析
> 本节适用于从 SDK 53 起的所有平台。
Metro 会为 ES Module 的 `import` 和 CommonJS 的 `require` 使用不同的解析策略。
之前,Metro 采用经典的 Node.js 模块解析策略(与 v12 之前的 Node.js 版本一致),并做了一些额外调整来支持 ES Modules。在这种解析策略下,Metro 会从 `node_modules`、JS 文件中解析模块,必要时可以省略扩展名(例如 `.js`),并使用 `package.json` 中的 `main`、`module` 和 `react-native` 等字段。
现在,随着现代 ES Modules 解析策略的引入,Metro 会先从 `node_modules` 中解析模块,然后匹配不同的 `package.json` 字段,例如 `exports`、[包暴露的子路径的嵌套映射](https://nodejs.org/api/packages.html#conditional-exports) 和 `main`。
根据包的导入方式,这两种解析策略中的一种会被使用。通常,从 Node 模块中使用 `import` 导入的文件(而不是 `require`)会使用 ES Modules 解析策略,并在必要时回退到常规经典 Node.js 解析。未使用 ES Modules 解析,或者通过 CommonJS `require` 导入的文件,则会使用经典解析策略。
### `package.json:exports`
在执行 ES Modules 解析时,Metro 会查看 `package.json:exports` 条件映射。这个映射将导入子路径和条件映射到 Node 模块包中的文件。
例如,一个始终暴露 **index.js** 文件,并且符合 Metro 经典 CommonJS 模块解析的包,可以通过 `default` 条件指定一个映射。
```json
{
"exports": {
"default": "./index.js"
}
}
```
不过,同时提供 CommonJS 和 ES Modules 入口点的包,可以通过 `import` 和 `require` 条件提供映射。
```json
{
"exports": {
"import": "./index.mjs",
"require": "./index.cjs"
}
}
```
默认情况下,Metro 会根据平台以及解析是从 CommonJS `require` 调用开始,还是从 ES Modules `import` 语句开始,来匹配不同的条件,并相应地更改条件。
对于原生平台,会添加 `react-native` 条件;对于 web 导出,会添加 `browser` 条件;对于服务器导出(例如 API routes 或 React Server functions),会添加 `node`、`react-server` 和 `workerd` 条件。这些条件不会按照它们定义的顺序匹配,而是会按照 `package.json:exports` 映射中的属性顺序进行匹配。
TypeScript 会独立于 Metro 执行 ES Module 解析,并且在其 `compilerOptions.moduleResolution` 配置选项设置为 `"bundler"`(这与 Metro 的行为更接近)或 `"node16"` / `"nodenext"` 时,也会遵守 `package.json:exports` 映射。不过,TypeScript 还会匹配 `types` 条件。因此,当某个包没有把 `types` 条件放在其 exports 映射的首位时,类型可能无法正确解析。
由于 exports 映射可能包含子路径,包导入不再一定需要匹配包 modules 文件夹中的某个文件,而可能是一个“重定向”导入。如果在 `package.json:exports` 中指定了,导入 `'package/submodule'` 可能会匹配到与 **node_modules/package/submodule.js** 不同的文件。
```json
{
"exports": {
".": "./index.js",
"./submodule": "./submodule/submodule.js"
}
}
```
如果你遇到与新的 ES Modules 解析策略不兼容或尚未准备好的包,你可以通过补丁修改其 `package.json` 文件并添加或修正其 `package.json:exports` 条件映射来解决问题。不过,也可以通过禁用 `unstable_enablePackageExports` 选项来阻止 Metro 在解析中使用 `package.json:exports` 映射。
```js
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
config.resolver.unstable_enablePackageExports = false;
module.exports = config;
```
## 资产导入
当导入资产时,会创建一个虚拟模块来表示导入该资产所需的数据。
在原生平台上,资产将是一个数字 ID:`1`、`2`、`3`,等等,可以通过 `require("@react-native/assets-registry/registry").getAssetByID()` 来查找。在 web 和服务器平台上,资产会根据文件类型而变化。如果文件是图片,那么资产将是 `{ uri: string, width?: number, height?: number }`,否则资产将是一个表示该资产远程 URL 的 `string`。从 SDK 55 起,你可以使用 `String(asset)` 来获取 web 上任意资产的公开 URL,这不包括无法包含 `toString` 函数的 React Server Component 环境。
资产可以如下使用:
```jsx
import { Image } from 'react-native';
import asset from './img.png';
function Demo() {
return ;
}
```
在 API 路由中,你始终可以假设资产的类型不会是数字:
```js
import asset from './img.png';
export async function GET(req: Request) {
const ImageData = await fetch(
new URL(
// 访问资产 URI。
asset.uri,
// 附加到当前请求 URL 的 origin。
req.url
)
).then(res => res.arrayBuffer());
return new Response(ImageData, {
headers: {
'Content-Type': 'image/png',
},
});
}
```
## Web workers
> **重要** 此功能为 [alpha](/more/release-statuses#alpha) 版本,并可能发生破坏性变更。
```ts
new Worker(new URL('./worker', window.location.href));
```
Expo Metro 提供实验性的 web worker 支持。此功能目前仅支持 web,不能在原生平台上使用,在原生平台上使用会触发错误 "Property 'Worker' doesn't exist"。
Web worker 可用于将工作卸载到 web 上的单独线程,从而让主线程保持响应。这对于计算开销较大的任务很有用,例如图像处理、加密或其他会阻塞主线程的任务。
Worker 可以使用 `Blob` 内联生成,但有时你可能希望利用 TypeScript 等现代特性,或导入其他模块。
Web worker 依赖于 Expo 的 bundle 拆分支持,这意味着你需要使用 Expo Router,或者安装并导入 `@expo/metro-runtime`。你也不能在 web worker 中使用环境变量 `EXPO_NO_METRO_LAZY=1`。
请看下面这个将数字翻倍的 worker 示例:
```ts
self.onmessage = ({ data }) => {
const result = data * 2; // 示例:将数字翻倍
self.postMessage(result);
};
```
这个 worker 文件可以在主应用中作为 `Worker` 导入:
```ts
// worker 的类型为 `Worker`
const worker = new Worker(new URL('./worker', window.location.href));
worker.onmessage = ({ data }) => {
console.log(`Worker responded: ${data}`);
};
worker.postMessage(5);
```
在幕后,Expo CLI 正在生成如下代码:
```ts
const worker = new Worker(
new URL('/worker.bundle?platform=web&dev=true&etc', window.location.href)
);
```
生成的 bundle URL 会根据开发/生产环境而变化,以确保 worker 被正确加载并打包。不同于传统的 bundle 拆分,worker 文件需要包含其自身对所有模块的副本,并且不能依赖主 bundle 中的公共模块。
原生 API `Worker` 传统上在 React Native 中不可用,并且 Expo SDK 也未提供,因此即使这个打包功能在技术上适用于所有平台,它也只对 web 有用。如果你希望同时支持原生平台,从理论上说你可以编写一个原生 Expo 模块来为 `Worker` API 提供 polyfill。或者,你也可以在 React Native Reanimated 中使用 "worklet" API,将工作卸载到原生端的单独线程。
另外,你也可以通过公共路径导入 Worker:先将一个转换后的 JS 文件放入 **public** 目录,然后在 worker 导入中使用一个变量引用它:
```ts
// 这将避免转换,并直接使用公共路径。
const worker = new Worker('/worker.js');
// 这个变量会破坏转换,导致使用字面路径而不是转换后的路径。
const path = '/worker.js';
const anotherWorker = new Worker(new URL(path, window.location.href));
```
在 `Worker` 构造函数中使用变量不支持打包。若要检查内部 URL,你可以使用内部语法 `require.unstable_resolveWorker('./path/to/worker.js')` 来获取 URL 片段。
## Bare workflow 设置
> 本指南是版本相关的,在升级/降级 Expo 时需要重新查看。或者,使用 [Expo Prebuild](/more/glossary-of-terms#prebuild) 来进行完全自动化的设置。
不使用 [Expo Prebuild](/more/glossary-of-terms#prebuild) 的项目必须配置原生文件,以确保始终使用 Expo Metro 配置来打包项目。
这些修改旨在分别将 `npx react-native bundle` 和 `npx react-native start` 替换为 `npx expo export:embed` 和 `npx expo start`。
### metro.config.js
确保 **metro.config.js** 继承自 `expo/metro-config`:
```js
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
module.exports = config;
```
### `android/app/build.gradle`
Android 的 **app/build.gradle** 必须配置为在生产打包时使用 Expo CLI。修改 `react` 配置对象:
### `ios/.xcodeproj/project.pbxproj`
在你的 **ios/.xcodeproj/project.pbxproj** 文件中,替换以下脚本:
#### "Start Packager" 脚本
移除 **"Start Packager"** 脚本。必须在运行应用之前或之后使用 `npx expo` 启动开发服务器。
#### "Bundle React Native code and images" 脚本
或者,在 Xcode 项目中,选择 **"Bundle React Native code and images"** 构建阶段,并添加以下修改:
> 你可以设置 `CLI_PATH`、`BUNDLE_COMMAND` 和 `ENTRY_FILE` 环境变量来覆盖这些默认值。
### 自定义入口文件
默认情况下,React Native 仅支持使用根目录下的 `index.js` 文件作为入口文件(或类似 `index.ios.js` 这样的平台特定变体)。Expo 项目允许使用任意入口文件,但这需要额外的裸工作流设置。
#### 开发
可以通过使用 [`expo-dev-client`](/versions/latest/sdk/dev-client) 包来启用开发模式入口文件。或者,你也可以添加以下配置:
#### 生产
在你的 **ios/.xcodeproj/project.pbxproj** 文件中,根据 Metro 将 **"Bundle React Native code and images"** 脚本替换为设置 `$ENTRY_FILE`:
Android 的 **app/build.gradle** 必须配置为使用 Metro 模块解析来查找根入口文件。修改 `react` 配置对象:
---
---
title: package.json
description: package.json 文件中可使用的 Expo 特定属性参考。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/config/package-json/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# package.json
package.json 文件中可使用的 Expo 特定属性参考。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
**package.json** 是一个 JSON 文件,包含 JavaScript 项目的元数据。这是对可在 **package.json** 文件中使用的 Expo 特定属性的参考。
## `install.exclude`
以下命令会对项目中已安装的库执行版本检查,并在某个库的版本与 Expo 推荐的版本不同的时候给出警告:
- `npx expo start` 和 `npx expo-doctor`
- `npx expo install`(在安装该库的新版本时,或使用 `--check` 或 `--fix` 选项时)
通过在 **package.json** 文件中的 `install.exclude` 数组里指定该库,你可以将其排除在版本检查之外:
```json
{
"expo": {
"install": {
"exclude": ["expo-updates", "expo-splash-screen"]
}
}
}
```
## `autolinking`
允许通过在 **package.json** 中使用 `autolinking` 属性来配置模块解析行为。
完整参考请参见 [Autolinking configuration](/modules/autolinking#configuration)。
## `doctor`
允许配置 [`npx expo-doctor`](/develop/tools#expo-doctor) 命令的行为。
### `reactNativeDirectoryCheck`
默认情况下,Expo Doctor 会将你的项目包与 [React Native directory](https://reactnative.directory/) 进行验证。此检查会对未包含在 React Native Directory 中的包列表发出警告。
你可以通过在项目的 **package.json** 文件中添加以下配置来自定义此检查:
```json
{
"expo": {
"doctor": {
"reactNativeDirectoryCheck": {
"enabled": true,
"exclude": ["/foo/", "bar"],
"listUnknownPackages": true
}
}
}
}
```
默认情况下,此检查已启用,并会列出未知包。
### `appConfigFieldsNotSyncedCheck`
Expo Doctor 会检查你的项目是否包含原生项目目录,例如 **android** 或 **ios**。如果这些目录存在,但未列在你的 **.gitignore** 或 [**.easignore**](/build-reference/easignore) 文件中,Expo Doctor 会验证是否存在应用配置文件。如果该文件存在,这意味着你的项目已配置为使用 [Prebuild](/more/glossary-of-terms#prebuild)。
当 **android** 或 **ios** 目录存在时,EAS Build 不会将应用配置属性同步到原生项目。如果这些条件成立,Expo Doctor 会发出警告。
你可以通过在项目的 **package.json** 文件中添加以下配置来禁用或启用此检查:
```json
{
"expo": {
"doctor": {
"appConfigFieldsNotSyncedCheck": {
"enabled": false
}
}
}
}
```
---
---
title: Expo SDK 参考
description: 使用 Expo SDK 包在你的 Expo 和 React Native 应用中访问设备和系统功能。
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo SDK 参考
使用 Expo SDK 包在你的 Expo 和 React Native 应用中访问设备和系统功能。
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
Expo SDK 是一组提供访问设备和系统功能的包,例如相机、联系人、位置、传感器、触觉反馈等。每个包都针对特定功能,可独立使用。所有包都可在安装了 `expo` 包的任何 React Native 应用中正常工作。
您可以使用 [`npx expo install`](/more/expo-cli#install) 命令安装任意 Expo SDK 包。例如,以下命令会安装三个不同的包:
```sh
npx expo install expo-camera expo-contacts expo-sensors
```
安装一个或多个包后,您可以将它们导入到您的 JavaScript 代码中:
```js
import { CameraView } from 'expo-camera';
import * as Contacts from 'expo-contacts';
import { Gyroscope } from 'expo-sensors';
```
这使您可以编写 [`Contacts.getContactsAsync()`](/versions/latest/sdk/contacts#contactsgetcontactsasynccontactquery) 并从设备读取联系人,读取陀螺仪传感器以检测设备移动,或者启动手机相机并拍照。
## 所有 Expo SDK 包都可在任何 React Native 应用中使用
Expo 应用本质上就是 React Native 应用,因此所有 Expo SDK 包都可在安装并配置了 `expo` 包的任何 React Native 应用中使用。创建支持 Expo SDK 包的 React Native 应用最简单的方法是使用 `create-expo-app`。不过,您也可以通过 `npx install-expo-modules` 命令为现有的 React Native 应用添加 Expo SDK 支持。
```sh
npx create-expo-app my-app --template bare-minimum
```
[在现有 React Native 应用中安装 Expo SDK 包](/bare/installing-expo-modules) — 了解更多关于如何将使用 npx @react-native-community/cli@latest init 创建的项目配置为支持 Expo SDK 包。 — npx @react-native-community/cli@latest init
[使用库](/workflow/using-libraries) — 了解如何在您的项目中安装 Expo SDK 包。
## 使用预发布版本
新的 Expo SDK 版本每年发布三次。在这些发布之间,我们会发布 `expo` 包以及所有 Expo SDK 包的预发布版本。预发布版本不被视为稳定版,仅应在您能接受遇到 bug 或其他问题风险的情况下使用。
### 金丝雀版本
金丝雀版本代表其发布时 `main` 分支状态的快照。金丝雀包版本名称中包含 `-canary`,以及日期和提交哈希,例如 `55.0.0-canary-20260121-a63c0dd`。要安装最新的金丝雀版本:
```sh
npm install expo@canary && npx expo install --fix
```
您通常可以将单个包的预发布版本与 Expo SDK 的稳定版本一起使用。金丝雀级别的发布有时可能会出现不兼容或其他问题。如果您选择使用金丝雀包,并且已验证其在您的使用场景中表现良好,您可能希望[关闭依赖验证警告](/more/expo-cli#configuring-dependency-validation)。
### Beta 版本
在每次 Expo SDK 发布之前,我们都会发布 `expo` 包以及所有 Expo SDK 包的 beta 版本。Beta 版本被认为比金丝雀版本稳定得多,我们鼓励开发者在自己的应用中尝试它们并分享反馈。Beta 版本在 npm 上使用 `beta` 标签,并遵循相关 [更新日志](https://expo.dev/changelog) 帖子中的说明。
## 每个 Expo SDK 版本都依赖于特定的 React Native 版本
| Expo SDK version | React Native version | React version | React Native Web version | React Native TV version | Minimum Node.js version |
| --- | --- | --- | --- | --- | --- |
| 55.0.0 | 0.83 | 19.2.0 | 0.21.0 | 0.83-stable | 20.19.x |
| 54.0.0 | 0.81 | 19.1.0 | 0.21.0 | 0.81-stable | 20.19.x |
| 53.0.0 | 0.79 | 19.0.0 | 0.20.0 | 0.79-stable | 20.18.x |
### 其他信息
Expo SDK 跟踪 React Native 发布的策略
- Expo SDK 版本每年发布三次,每个 Expo SDK 发布都对应一个 React Native 版本。通常是发布时最新的稳定版本。
- React Native 的发布节奏在其发展历史中有所变化,目前计划在 2025 年发布六次。在这样的节奏下,您可以预期每两个 React Native 版本都会对应一个 Expo SDK 版本。
- 即将发布的 Expo SDK 的预发布版本会很快支持最新版本的 React Native,通常在其发布当天即可支持。Expo SDK 团队的一名成员会参与每次 React Native 发布团队的工作,并负责持续更新 Expo 仓库中的 React Native 版本、验证兼容性,并将回归问题反馈给 Meta 团队。
为什么不在每次 React Native 发布后立即发布一个新的 Expo SDK 版本?
在 Expo,我们发现每年发布三个主要版本,能够在依赖我们开源工具的开发者所需的稳定性与创新之间取得良好平衡。Expo 与 Meta 在发布方面密切合作,我们将继续改进流程,以尽可能快地将最新的 Expo 和 React Native 功能带给您。
如果我需要最新 React Native 版本中的一个更改,但它还没有出现在 Expo SDK 发布中,该怎么办?
我们与 Meta 团队密切合作,确保任何紧急修复都会包含在最新 Expo SDK 所使用的 React Native 版本中。如果您的问题因为过于小众而无法被挑选进入现有版本,或者它涉及破坏性更改,那么您有两个选择:
1. 使用 [`patch-package`](https://github.com/ds300/patch-package) 引入该修复。
2. 使用 [Expo SDK 的预发布版本](/versions/latest#using-pre-release-versions)。([示例](https://expo.dev/changelog/react-native-78))。
我可以在最新的 Expo SDK 中使用较旧版本的 React Native 吗?
Expo SDK 中的包旨在支持该 SDK 对应的目标 React Native 版本。通常,它们不支持较旧版本的 React Native,但也可能支持。当发布新的 React Native 版本时,Expo SDK 包的最新版本通常会更新以支持它。不过,这可能需要数周甚至更久,具体取决于该版本中的变更范围。
## 对 Android 和 iOS 版本的支持
每个版本的 Expo SDK 都支持 Android 和 iOS 的最低操作系统版本。对于 Android,定义了 `compileSdkVersion`,它会告诉 [Gradle](https://developer.android.com/studio/build) 使用哪个 Android SDK 版本来编译应用。这也意味着您可以使用该 SDK 版本以及之前版本中包含的 Android API 功能。对于 iOS,[Xcode](https://developer.apple.com/news/upcoming-requirements/) 会指定用于编译应用的最低 Xcode SDK 版本。
| Expo SDK version | Android version | `compileSdkVersion` | `targetSdkVersion` | iOS version | Xcode version |
| --- | --- | --- | --- | --- | --- |
| 55.0.0 | 7+ | 36 | 36 | 15.1+ | 26.2+ |
| 54.0.0 | 7+ | 36 | 36 | 15.1+ | 16.1+ |
| 53.0.0 | 7+ | 35 | 35 | 15.1+ | 16.0+ |
在决定是否升级 Expo SDK 版本时,请同时考虑 Expo 的 SDK 版本和应用商店提交要求,如上表所述。Google Play 商店和 Apple App Store 会定期提高最低所需的操作系统版本和 API 等级,而这些是提交新应用所必需的。Expo 无法控制应用商店的要求,您应查看 [Google](https://developer.android.com/studio/build) 和 [Apple](https://developer.apple.com/news/upcoming-requirements/) 以了解当前的应用商店提交要求。
---
---
title: 加速度计
description: 一个提供访问设备加速度计传感器的库。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-sensors'
packageName: 'expo-sensors'
iconUrl: '/static/images/packages/expo-sensors.png'
platforms: ['android', 'ios*', 'web', 'expo-go']
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/accelerometer/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo 加速度计
一个提供访问设备加速度计传感器的库。
Android, iOS (device only), Web, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo-sensors` 中的 `Accelerometer` 提供对设备加速度计传感器及相关监听器的访问,用于响应三维空间中加速度的变化,也就是任何移动或振动。
## 安装
```sh
npx expo install expo-sensors
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## 用法
```jsx
import { useState, useEffect } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { Accelerometer } from 'expo-sensors';
export default function App() {
const [{ x, y, z }, setData] = useState({
x: 0,
y: 0,
z: 0,
});
const [subscription, setSubscription] = useState(null);
const _slow = () => Accelerometer.setUpdateInterval(1000);
const _fast = () => Accelerometer.setUpdateInterval(16);
const _subscribe = () => {
setSubscription(Accelerometer.addListener(setData));
};
const _unsubscribe = () => {
subscription && subscription.remove();
setSubscription(null);
};
useEffect(() => {
_subscribe();
return () => _unsubscribe();
}, []);
return (
加速度计:(单位为 g,其中 1g = 9.81 m/s^2)x: {x}y: {y}z: {z}{subscription ? '开启' : '关闭'}慢快
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 20,
},
text: {
textAlign: 'center',
},
buttonContainer: {
flexDirection: 'row',
alignItems: 'stretch',
marginTop: 15,
},
button: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#eee',
padding: 10,
},
middleButton: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderColor: '#ccc',
},
});
```
## API
```js
import { Accelerometer } from 'expo-sensors';
```
## Classes
### `Accelerometer`
Supported platforms: Android, iOS, Web.
Type: Class extends [DeviceSensor](/versions/latest/sdk/sensors)<[AccelerometerMeasurement](#accelerometermeasurement)\>
A base class for subscribable sensors. The events emitted by this class are measurements specified by the parameter type `Measurement`.
Accelerometer Methods
### `addListener(listener)`
Supported platforms: Android, iOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `listener` | Listener<[AccelerometerMeasurement](#accelerometermeasurement)\> | A callback that is invoked when an accelerometer update is available. When invoked, the listener is provided a single argument that is an `AccelerometerMeasurement` object. |
Subscribe for updates to the accelerometer.
Returns: `EventSubscription`
A subscription that you can call `remove()` on when you would like to unsubscribe the listener.
### `getListenerCount()`
Supported platforms: Android, iOS, Web.
Returns the registered listeners count.
Returns: `number`
### `getPermissionsAsync()`
Supported platforms: Android, iOS, Web.
Checks user's permissions for accessing sensor.
Returns: `Promise`
### `hasListeners()`
Supported platforms: Android, iOS, Web.
Returns boolean which signifies if sensor has any listeners registered.
Returns: `boolean`
### `isAvailableAsync()`
Supported platforms: Android, iOS, Web.
> You should always check the sensor availability before attempting to use it.
Returns whether the accelerometer is enabled on the device.
On mobile web, you must first invoke `Accelerometer.requestPermissionsAsync()` in a user interaction (i.e. touch event) before you can use this module. If the `status` is not equal to `granted` then you should inform the end user that they may have to open settings.
On **web** this starts a timer and waits to see if an event is fired. This should predict if the iOS device has the **device orientation** API disabled in **Settings > Safari > Motion & Orientation Access**. Some devices will also not fire if the site isn't hosted with **HTTPS** as `DeviceMotion` is now considered a secure API. There is no formal API for detecting the status of `DeviceMotion` so this API can sometimes be unreliable on web.
Returns: `Promise`
A promise that resolves to a `boolean` denoting the availability of the accelerometer.
### `removeAllListeners()`
Supported platforms: Android, iOS, Web.
Removes all registered listeners.
Returns: `void`
> **Deprecated:** use subscription.remove() instead.
### `removeSubscription(subscription)`
Supported platforms: Android, iOS, Web.
| Parameter | Type |
| --- | --- |
| `subscription` | `EventSubscription` |
Returns: `void`
### `requestPermissionsAsync()`
Supported platforms: Android, iOS, Web.
Asks the user to grant permissions for accessing sensor.
Returns: `Promise`
### `setUpdateInterval(intervalMs)`
Supported platforms: Android, iOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `intervalMs` | `number` | Desired interval in milliseconds between sensor updates. Starting from Android 12 (API level 31), the system has a 200Hz limit for each sensor updates. |
Set the sensor update interval.
Returns: `void`
## Interfaces
### `Subscription`
Supported platforms: Android, iOS, Web.
A subscription object that allows to conveniently remove an event listener from the emitter.
Subscription Methods
### `remove()`
Supported platforms: Android, iOS, Web.
Removes an event listener for which the subscription has been created. After calling this function, the listener will no longer receive any events from the emitter.
Returns: `void`
## Types
### `AccelerometerMeasurement`
Supported platforms: Android, iOS, Web.
Each of these keys represents the acceleration along that particular axis in g-force (measured in `g`s).
A `g` is a unit of gravitational force equal to that exerted by the earth’s gravitational field (`9.81 m/s^2`).
| Property | Type | Description |
| --- | --- | --- |
| timestamp | `number` | Timestamp of the measurement in seconds. |
| x | `number` | Value of `g`s device reported in X axis. |
| y | `number` | Value of `g`s device reported in Y axis. |
| z | `number` | Value of `g`s device reported in Z axis. |
### `PermissionExpiration`
Supported platforms: Android, iOS, Web.
Literal Type: `union`
Permission expiration time. Currently, all permissions are granted permanently.
Acceptable values are: `'never'` | `number`
### `PermissionResponse`
Supported platforms: Android, iOS, Web.
An object obtained by permissions get and request functions.
| Property | Type | Description |
| --- | --- | --- |
| canAskAgain | `boolean` | Indicates if user can be asked again for specific permission. If not, one should be directed to the Settings app in order to enable/disable the permission. |
| expires | `PermissionExpiration` | Determines time when the permission expires. |
| granted | `boolean` | A convenience boolean that indicates if the permission is granted. |
| status | `PermissionStatus` | Determines the status of the permission. |
## Enums
### `PermissionStatus`
Supported platforms: Android, iOS, Web.
#### `DENIED`
`PermissionStatus.DENIED = "denied"`
User has denied the permission.
#### `GRANTED`
`PermissionStatus.GRANTED = "granted"`
User has granted the permission.
#### `UNDETERMINED`
`PermissionStatus.UNDETERMINED = "undetermined"`
User hasn't granted or denied the permission yet.
---
---
title: AgeRange
description: 一个通过 Android 上的 Play Age Signals API 和 iOS 上的 Declared Age Range 框架提供年龄范围信息访问的库。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-age-range'
packageName: 'expo-age-range'
platforms: ['android', 'ios', 'expo-go']
isAlpha: true
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/age-range/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo AgeRange
一个通过 Android 上的 Play Age Signals API 和 iOS 上的 Declared Age Range 框架提供年龄范围信息访问的库。
Android, iOS, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
> **重要** **此库目前处于 [alpha](/more/release-statuses#alpha) 阶段,并且会频繁出现破坏性变更。**
`expo-age-range` 提供对用户年龄范围信息的访问。它在 Android 上使用 Google 的 [Play Age Signals API](https://developer.android.com/google/play/age-signals/use-age-signals-api),在 iOS 上使用 Apple 的 [Declared Age Range framework](https://developer.apple.com/documentation/declaredagerange/)。
此库允许你从应用用户那里请求年龄范围信息,以帮助你遵守适龄内容法规(例如 [美国得克萨斯州](https://developer.apple.com/news/?id=btkirlj8) 的相关要求),并在应用中提供适龄体验。
### 限制
我们强烈建议在真机上测试该功能,因为模拟器运行时可能无法按预期工作。
## 安装
```sh
npx expo install expo-age-range
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## 在 app 配置中进行配置
### 设置 iOS 项目
要在 iOS 上使用年龄范围 API,你需要使用 Xcode 26.0 或更高版本构建项目。需要 `com.apple.developer.declared-age-range` entitlement。将其添加到你的 [app config](/versions/latest/config/app) 文件中:
```json
{
"expo": {
"ios": {
"entitlements": {
"com.apple.developer.declared-age-range": true
}
}
}
}
```
Are you using this library in an existing React Native app?
对于现有的 React Native 项目,将该 entitlement 添加到项目的 **ios/[app]/[app].entitlements** 文件中:
```xml
com.apple.developer.declared-age-range
```
## 使用
```tsx
import * as AgeRange from 'expo-age-range';
import { useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default function App() {
const [result, setResult] = useState(null);
const requestAgeRange = async () => {
try {
const ageRange = await AgeRange.requestAgeRangeAsync({
threshold1: 10,
threshold2: 13,
threshold3: 18,
});
setResult(ageRange);
} catch (error) {
setResult({ error: error.message });
}
};
return (
{result && (
{'error' in result ? `错误: ${result.error}` : `下限年龄: ${result.lowerBound}`}
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
result: {
marginTop: 20,
fontSize: 16,
},
});
```
## 其他资源
- [Play Age Signals API](https://developer.android.com/google/play/age-signals/use-age-signals-api):Android 的年龄信号文档
- [Declared Age Range framework](https://developer.apple.com/documentation/declaredagerange/):iOS 的声明年龄范围文档
## API
```ts
import * as AgeRange from 'expo-age-range';
```
## Methods
### `AgeRange.requestAgeRangeAsync(options)`
Supported platforms: Android, iOS 26.0+.
| Parameter | Type |
| --- | --- |
| `options` | [AgeRangeRequest](#agerangerequest) |
Prompts the user to share their age range with the app. Responses may be cached by the OS for future requests.
Returns: `Promise`
A promise that resolves with user's age range response, or rejects with an error. The user needs to be signed in on the device to get a valid response. When not supported (earlier than iOS 26 and web), the call returns `lowerBound: 18`, which is equivalent to the response of an adult user.
## Types
### `AgeRangeRequest`
Supported platforms: iOS.
Options for requesting age range information from the user.
| Property | Type | Description |
| --- | --- | --- |
| threshold1 | `number` | The required minimum age for your app. |
| threshold2(optional) | `number` | An optional additional minimum age for your app. |
| threshold3(optional) | `number` | An optional additional minimum age for your app. |
### `AgeRangeResponse`
Supported platforms: Android, iOS.
Response containing the user's age range information.
Contains age boundaries and platform-specific metadata.
| Property | Type | Description |
| --- | --- | --- |
| activeParentalControls(optional) | `string[]` | Supported platforms: iOS. List of parental controls enabled and shared as a part of age range declaration. |
| ageRangeDeclaration(optional) | `'selfDeclared' | 'guardianDeclared'` | Supported platforms: iOS. Indicates whether the age range was declared by the user themselves or someone else (parent, guardian, or Family Organizer in a Family Sharing group). |
| installId(optional) | `string` | Supported platforms: Android. An ID assigned to supervised user installs by Google Play, used to notify you of revoked app approval. |
| lowerBound(optional) | `number` | The lower limit of the person’s age range. |
| mostRecentApprovalDate(optional) | `number` | Supported platforms: Android. The effective date (timestamp) of the most recent significant change that was approved. |
| upperBound(optional) | `number` | The upper limit of the person’s age range. |
| userStatus(optional) | `'VERIFIED' | 'SUPERVISED' | 'SUPERVISED_APPROVAL_PENDING' | 'SUPERVISED_APPROVAL_DENIED' | 'DECLARED' | 'UNKNOWN'` | Supported platforms: Android. The user's age verification or supervision status. |
## 错误代码
可在原生模块抛出的任何错误的 `code` 属性中获取。有关 Android 特定的错误代码,请参见 [Play Age Signals API 文档](https://developer.android.com/google/play/age-signals/use-age-signals-api#handle-api-errors) 中的 “Handle API error codes”。
| Code | Platform | Description |
| --- | --- | --- |
| `ERR_AGE_RANGE_USER_DECLINED` | iOS | 用户拒绝共享其年龄范围。 |
| `ERR_AGE_RANGE_NOT_AVAILABLE` | iOS | 年龄范围不可用。最可能的原因是用户未在设备上登录其 Apple 账号。 |
| `ERR_AGE_RANGE_INVALID_REQUEST` | iOS | 所提供的参数无效。年龄范围之间需要至少相隔 2 年。 |
---
---
title: AppIntegrity
description: 一个库,提供对 Android 上的 Google Play Integrity API 和 iOS 上的 Apple App Attest 服务的访问。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-app-integrity'
packageName: '@expo/app-integrity'
platforms: ['android', 'ios', 'expo-go']
isAlpha: true
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/app-integrity/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# AppIntegrity
一个库,提供对 Android 上的 Google Play Integrity API 和 iOS 上的 Apple App Attest 服务的访问。
Android, iOS, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
> **重要** **此库目前处于 [alpha](/more/release-statuses#alpha) 阶段,并且将频繁发生破坏性变更。**
`@expo/app-integrity` 提供了 API,帮助确保你的后端资源仅被运行在真实设备上的、你应用的合法安装实例访问。它在 Android 上使用 Google 的 [Play Integrity APIs](https://developer.android.com/google/play/integrity),在 iOS 上使用 Apple 的 [App Attest service](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity) 来验证应用的真实性,帮助防止未经授权的客户端、被修改的应用或自动化脚本向你的服务器发起请求。
通常,`@expo/app-integrity` 可帮助你的服务器区分以下两者:
- 运行在**真实设备**上的**真实应用**
- 其他任何情况(被修改的应用、脚本、模拟器)
它通过使用平台推荐的应用证明服务来实现这一点。
## 安装
```sh
npx expo install @expo/app-integrity
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## Android 上的用法
`@expo/app-integrity` 使用 Play Integrity 的 [标准请求流程](https://developer.android.com/google/play/integrity/standard)进行完整性检查。
### 配置
请参阅 [Play Integrity 设置指南](https://developer.android.com/google/play/integrity/setup#set-integrity-responses),了解如何在你的应用中启用完整性 API。
### 准备完整性令牌提供程序(一次性)
在发起完整性检查请求之前,你需要先准备完整性令牌提供程序。你可以在应用启动时执行此操作,或者在需要完整性检查之前在后台完成。
```js
import * as AppIntegrity from '@expo/app-integrity';
const cloudProjectNumber = 'your-cloud-project-number';
await AppIntegrity.prepareIntegrityTokenProviderAsync(cloudProjectNumber);
```
### 请求完整性令牌(按需)
每当你的应用发起你希望验证真实性的服务器请求时,你都需要请求一个完整性令牌,并将其发送到应用的后端服务器进行解密和验证。然后,后端服务器可以决定如何处理。
```js
const requestHash = '2cp24z...';
const result = await AppIntegrity.requestIntegrityCheckAsync(requestHash);
```
在调用 [`requestIntegrityCheckAsync`](/versions/latest/sdk/app-integrity#appintegrityrequestintegritycheckasyncrequesthash) 之前,请确保已成功调用 [`prepareIntegrityTokenProviderAsync`](/versions/latest/sdk/app-integrity#appintegrityprepareintegritytokenproviderasynccloudprojectnumber)。
在此示例中,`requestHash` 是与正在验证的特定用户操作唯一对应的哈希。对于不同的用户操作,你可以使用不同的哈希多次调用 [`requestIntegrityCheckAsync`](/versions/latest/sdk/app-integrity#appintegrityprepareintegritytokenproviderasynccloudprojectnumber)。
成功后,将结果发送到你的服务器进行验证。
> **注意**:如果你的应用长时间使用同一个令牌提供程序,令牌提供程序可能会过期,从而在下一次令牌请求时导致 `ERR_APP_INTEGRITY_PROVIDER_INVALID` 错误。你应通过再次调用 `prepareIntegrityTokenProviderAsync` 来请求新的提供程序,从而处理此错误。
### 解密并验证完整性判定结果
请参阅 [Play Integrity 指南](https://developer.android.com/google/play/integrity/standard#decrypt-and),了解如何在你的服务器中验证完整性令牌。
### 其他资源
- [Google Play Integrity 文档](https://developer.android.com/google/play/integrity/overview):请参阅 Google 的官方指南,了解支撑 `@expo/app-integrity` 的 API 和验证流程。
- [Play Integrity 标准请求流程](https://developer.android.com/google/play/integrity/standard):此页面描述了如何发起标准 API 请求来获取完整性判定结果,该流程支持 Android 5.0(API 级别 21)及更高版本。每当你的应用向服务器发起调用以检查交互是否真实时,都可以发起标准 API 请求来获取完整性判定结果。
- [关于完整性判定结果](https://developer.android.com/google/play/integrity/verdicts):完整性判定结果会传达有关设备、应用和账号有效性的信息。你的应用服务器可以使用解密并验证后的判定结果载荷,来决定如何针对应用中的特定操作或请求采取最佳处理方式。
- [处理错误代码](https://developer.android.com/google/play/integrity/reference/com/google/android/play/core/integrity/model/StandardIntegrityErrorCode):如果你的应用发起了 Play Integrity API 请求但调用失败,应用会收到一个错误代码。这些错误可能由于多种原因发生,例如网络连接较弱等环境问题、API 集成问题,或恶意活动与主动攻击。
## iOS 上的用法
### 配置
在 Xcode 中,进入 **Signing & Capabilities**,点击 **\+ Capability**,添加 **App Attest**。Xcode 会自动将所需的 entitlement 添加到你的应用中。
> **注意**:要使用 App Attest 服务,你的应用必须拥有一个你在 Apple Developer 网站上注册的 App ID。
有关服务器端的验证逻辑,请参阅 [验证连接到你服务器的应用](https://developer.apple.com/documentation/devicecheck/validating-apps-that-connect-to-your-server)。
### 检查设备是否支持应用证明
并非所有设备都能使用 App Attest 服务,因此在访问该服务之前,让应用先运行兼容性检查非常重要。如果用户的应用未通过兼容性检查,应优雅地绕过该服务。你可以通过读取 `isSupported` 属性来检查可用性。
```js
import * as AppIntegrity from '@expo/app-integrity';
if (AppIntegrity.isSupported) {
// 执行密钥生成和证明。
}
// 继续访问你的服务器 API。
```
> **注意**:App Attest 不支持 iOS 模拟器。
> **信息** 大多数应用扩展不支持 App Attest。通常,在这些扩展中执行代码时,即使 `isSupported` 方法属性为 `true`,也应绕过密钥生成和证明。唯一支持 App Attest 的应用扩展是 watchOS 9 或更高版本中的 watchOS 扩展。对于这些扩展,你可以使用 `isSupported` 的结果来判断你的 WatchKit 扩展是否应绕过证明。
### 创建密钥对
对于运行你应用的每台设备上的每个用户账号,通过调用 `generateKey` 方法生成一个唯一的、基于硬件的加密密钥对。
```js
const keyId = await AppIntegrity.generateKeyAsync();
```
成功后,该方法会返回一个密钥标识符(`keyId`),你稍后会用它来访问该密钥。请将该标识符记录在持久化存储中,因为没有标识符就无法使用该密钥,而且之后也无法再获取这个标识符。设备会自动将关联的私钥存储在 Secure Enclave 中,App Attest 服务可以从中使用它来创建签名,但任何进程都无法直接读取或修改它,从而确保其安全性。
> **信息** 如果你在 App Clip 中创建了密钥对,请在对应的完整应用中使用同一密钥对。为支持这一点,请务必将标识符存储在完整应用可访问的共享容器中。请参阅 Expo 关于使用 [expo-sqlite](https://docs.expo.dev/versions/latest/sdk/sqlite/#sharing-a-database-between-appsextensions-ios) 在应用/扩展之间共享数据库的指南,或者使用 React Native MMKV 的 [App Groups / extensions](https://github.com/mrousavy/react-native-mmkv?tab=readme-ov-file#app-groups-or-extensions) 共享存储来在两个目标之间持久化该标识符。
不要在同一设备上为多个用户重复使用同一个密钥,因为这会削弱安全防护。尤其是,这会使得检测一种攻击变得困难:攻击者利用一台被攻破的设备为多个远程用户提供被攻破版本的应用服务。更多信息请参阅 [评估欺诈风险](https://developer.apple.com/documentation/devicecheck/assessing-fraud-risk)。
### 从服务器获取挑战
从你的服务器请求一个唯一的、一次性的挑战。该挑战会嵌入到下面的证明步骤中,确保它不能被攻击者复用。该挑战应至少为 16 字节长,以提供足够的熵,使其无法被猜测。
### 将密钥对认证为有效
将 `keyId` 与前面步骤中从你的服务器创建的挑战一起传入 `attestKey` 方法,如下所示:
```js
const attestationObject = await AppIntegrity.attestKeyAsync(keyId, challenge);
```
成功后,将收到的 `attestationObject` 和 `keyId` 发送到你的服务器进行验证。
如果该方法返回 `ERR_APP_INTEGRITY_SERVER_UNAVAILABLE` 错误,请稍后使用同一个密钥再次尝试证明。对于任何其他错误,请丢弃该密钥标识符,并在下次重试时创建一个新密钥。
> **信息** 如果你的应用已经拥有数百万日活跃用户,并且你希望开始从应用中调用 `attestKey` 方法以发起证明,请查阅 [准备使用 app attest 服务](https://developer.apple.com/documentation/DeviceCheck/preparing-to-use-the-app-attest-service) 以了解如何安全地逐步放量用户。
如果服务器能够成功验证证明对象,就会判定该应用实例有效。在这种情况下,请务必将密钥标识符——而不是证明对象——持久化存储在应用中,以便将来用于对服务器请求进行签名。
### 对敏感请求生成断言
在成功验证某个密钥的证明后,你的服务器可以要求应用在未来的任意或全部服务器请求中证明其合法性。应用通过对请求进行签名来完成这一点。在应用中,从服务器获取一个唯一的、一次性的挑战。这里像证明一样使用挑战,是为了避免重放攻击。
```js
const challenge = 'A string from your server';
const request = {
action: 'getGameLevel',
levelId: '1234',
challenge: challenge,
};
const assertion = await AppIntegrity.generateAssertionAsync(keyId, JSON.stringify(request));
```
成功后,将断言对象连同客户端数据一起传递给服务器。如果断言对象验证失败,应由你来决定如何处理该请求。
使用一个密钥可以生成断言的次数没有限制。不过,通常你会将断言保留用于应用生命周期中敏感时刻发起的请求,例如应用下载高级内容时。
### 在重新安装后重新开始
你生成的密钥会在常规应用更新中保持有效,但在应用重新安装、设备迁移或从备份恢复设备时不会保留。在这些情况下,你需要从头开始并生成一个新密钥。尽量将新密钥生成限制在这些事件发生时,或者新增用户时。保持设备上的密钥数量较少,有助于检测某些类型的欺诈。
### 其他资源
- [Apple 的 App Attest 文档](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity):请参阅 Apple 的官方指南,了解支撑 `@expo/app-integrity` 的 API 和验证流程。
- [验证连接到你服务器的应用](https://developer.apple.com/documentation/devicecheck/validating-apps-that-connect-to-your-server):在你的服务器上验证应用证明和断言。
- [评估欺诈风险](https://developer.apple.com/documentation/devicecheck/assessing-fraud-risk):通过服务器到服务器的调用请求并分析风险数据。
- [准备使用 app attest 服务](https://developer.apple.com/documentation/devicecheck/preparing-to-use-the-app-attest-service):在开发环境中测试你的实现,并逐步引导用户上线。
## API
```js
import * as AppIntegrity from '@expo/app-integrity';
```
## Constants
### `AppIntegrity.isSupported`
Supported platforms: iOS.
Type: `boolean`
A boolean value that indicates whether a particular device provides the [App Attest](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity) service. Not all device types support the App Attest service, so check for support before using the service.
## Methods
### `AppIntegrity.attestKeyAsync(keyId, challenge)`
Supported platforms: iOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `keyId` | `string` | The identifier you received by calling the `generateKey` function. |
| `challenge` | `string` | A challenge string from your server. |
Asks Apple to attest to the validity of a generated cryptographic key.
Returns: `Promise`
A Promise that is fulfilled with a string that contains the attestation data. A statement from Apple about the validity of the key associated with keyId. Send this to your server for processing.
### `AppIntegrity.generateAssertionAsync(keyId, challenge)`
Supported platforms: iOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `keyId` | `string` | The identifier you received by calling the `generateKey` function. |
| `challenge` | `string` | A string to be signed with the attested private key. |
Creates a block of data that demonstrates the legitimacy of an instance of your app running on a device.
Returns: `Promise`
A Promise that is fulfilled with a string that contains the assertion object. A data structure that you send to your server for processing.
### `AppIntegrity.generateHardwareAttestedKeyAsync(keyAlias, challenge)`
Supported platforms: Android.
| Parameter | Type | Description |
| --- | --- | --- |
| `keyAlias` | `string` | A unique identifier for the key. |
| `challenge` | `string` | A challenge string from your server. |
Generates a hardware-attested key pair in the Android Keystore. This key can be used for attestation on GrapheneOS and other secure Android distributions.
Returns: `Promise`
A Promise that resolves when the key is generated successfully.
### `AppIntegrity.generateKeyAsync()`
Supported platforms: iOS.
Creates a new cryptographic key for use with the App Attest service.
Returns: `Promise`
A Promise that is fulfilled with a string that contains the key identifier. The key itself is stored securely in the Secure Enclave.
### `AppIntegrity.getAttestationCertificateChainAsync(keyAlias)`
Supported platforms: Android.
| Parameter | Type | Description |
| --- | --- | --- |
| `keyAlias` | `string` | The identifier of the key to get certificates for. |
Retrieves the attestation certificate chain for a hardware-attested key. The certificate chain can be validated on your server to verify device integrity.
Returns: `Promise`
A Promise that is fulfilled with an array of base64-encoded X.509 certificates.
### `AppIntegrity.isHardwareAttestationSupportedAsync()`
Supported platforms: Android.
Checks if hardware attestation is supported on this device.
Returns: `Promise`
A Promise that is fulfilled with a boolean indicating support.
### `AppIntegrity.prepareIntegrityTokenProviderAsync(cloudProjectNumber)`
Supported platforms: Android.
| Parameter | Type | Description |
| --- | --- | --- |
| `cloudProjectNumber` | `string` | The cloud project number. |
Prepares the integrity token provider for the given cloud project number.
Returns: `Promise`
A Promise that is fulfilled if the integrity token provider is prepared successfully.
### `AppIntegrity.requestIntegrityCheckAsync(requestHash)`
Supported platforms: Android.
| Parameter | Type | Description |
| --- | --- | --- |
| `requestHash` | `string` | A string representing the request hash. |
Requests an integrity verdict for the given request hash from Google Play.
Returns: `Promise`
A Promise that is fulfilled with a string that contains the integrity check result.
---
---
title: AppleAuthentication
description: 一个为 iOS 提供“使用 Apple 登录”功能的库。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-apple-authentication'
packageName: 'expo-apple-authentication'
platforms: ['ios', 'tvos', 'expo-go']
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/apple-authentication/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo AppleAuthentication
一个为 iOS 提供“使用 Apple 登录”功能的库。
iOS, tvOS, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo-apple-authentication` 为 iOS 提供 Apple 认证。它目前还不支持 Android 或 web。
任何包含第三方身份验证选项的应用**必须**提供 Apple 认证作为一种选项,以符合 App Store 审核指南。有关更多信息,请参阅 [Sign In with Apple](https://developer.apple.com/sign-in-with-apple/) 网站上的 Apple 认证。
## 安装
```sh
npx expo install expo-apple-authentication
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## 在 app 配置中进行配置
如果你在项目中使用配置插件([Continuous Native Generation (CNG)](/workflow/continuous-native-generation)),你可以使用 `expo-apple-authentication` 内置的 [config plugin](/config-plugins/introduction) 来进行配置。该插件允许你配置各种无法在运行时设置、且需要构建新的应用二进制文件后才会生效的属性。如果你的应用**不**使用 CNG,那么你需要手动配置该库。
### 设置 iOS 项目
要在你的应用中启用 **Sign In with Apple** 能力,请在项目的 app 配置中将 [`ios.usesAppleSignIn`](/versions/latest/config/app#usesapplesignin) 属性设为 `true`:
```json
{
"expo": {
"ios": {
"usesAppleSignIn": true
}
}
}
```
### Example app.json with config plugin
在本地运行 [EAS Build](/build/introduction) 将在构建前使用 [iOS capabilities signing](/build-reference/ios-capabilities) 来启用所需的能力。
```json
{
"expo": {
"plugins": ["expo-apple-authentication"]
}
}
```
Are you using this library in an existing React Native app?
不使用 [EAS Build](/build/introduction) 的应用必须为其 bundle identifier [手动配置](/build-reference/ios-capabilities#manual-setup) **Apple Sign In** 能力。
如果你通过 [Apple Developer Console](/build-reference/ios-capabilities#apple-developer-console) 启用了 **Apple Sign In** 能力,那么请务必在 **ios/[app]/[app].entitlements** 文件中添加以下 entitlement:
```xml
com.apple.developer.applesigninDefault
```
另外,请在你的 **ios/[app]/Info.plist** 中将 `CFBundleAllowMixedLocalizations` 设为 `true`,以确保登录按钮使用设备语言环境。
## 用法
```jsx
import * as AppleAuthentication from 'expo-apple-authentication';
import { View, StyleSheet } from 'react-native';
export default function App() {
return (
{
try {
const credential = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
// 已登录
} catch (e) {
if (e.code === 'ERR_REQUEST_CANCELED') {
// 处理用户取消登录流程的情况
} else {
// 处理其他错误
}
}
}}
/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
width: 200,
height: 44,
},
});
```
## 开发与测试
你可以在 iOS 上的 Expo Go 中测试这个库,而无需遵循上述任何说明。 不过,如果你使用的是 EAS Build,则需要添加 config plugin 才能使用这个库。 当你登录 Expo Go 时,你收到的标识符和值很可能会与你在独立应用中收到的不同。
你可以在 iOS 模拟器上对这个库进行有限测试。不过,并非所有方法的表现都会与真机相同, 因此我们强烈建议在开发过程中尽可能使用真机进行测试。
## 验证来自 Apple 的响应
Apple 的响应包含一个带有用户信息的已签名 JWT。为了确保该响应确实来自 Apple, 你可以使用 Apple 的公钥对签名进行加密验证,该公钥发布在 [https://appleid.apple.com/auth/keys。](https://appleid.apple.com/auth/keys%E3%80%82) 此过程并不特定于 Expo。
## API
```js
import * as AppleAuthentication from 'expo-apple-authentication';
```
## Component
### `AppleAuthenticationButton`
Supported platforms: iOS, tvOS.
Type: React.Element<[AppleAuthenticationButtonProps](#appleauthenticationbuttonprops)\>
This component displays the proprietary "Sign In with Apple" / "Continue with Apple" button on your screen. The App Store Guidelines require you to use this component to start the authentication process instead of a custom button. Limited customization of the button is available via the provided properties.
You should only attempt to render this if [`AppleAuthentication.isAvailableAsync()`](#appleauthenticationisavailableasync) resolves to `true`. This component will render nothing if it is not available, and you will get a warning in development mode (`__DEV__ === true`).
The properties of this component extend from `View`; however, you should not attempt to set `backgroundColor` or `borderRadius` with the `style` property. This will not work and is against the App Store Guidelines. Instead, you should use the `buttonStyle` property to choose one of the predefined color styles and the `cornerRadius` property to change the border radius of the button.
Make sure to attach height and width via the style props as without these styles, the button will not appear on the screen.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidbutton) for more details.
AppleAuthenticationButtonProps
### `buttonStyle`
Supported platforms: iOS, tvOS.
Type: [AppleAuthenticationButtonStyle](#appleauthenticationbuttonstyle)
The Apple-defined color scheme to use to display the button.
### `buttonType`
Supported platforms: iOS, tvOS.
Type: [AppleAuthenticationButtonType](#appleauthenticationbuttontype)
The type of button text to display ("Sign In with Apple" vs. "Continue with Apple").
### `cornerRadius`
Supported platforms: iOS, tvOS.
Optional • Type: `number`
The border radius to use when rendering the button. This works similarly to `style.borderRadius` in other Views.
### `onPress`
Supported platforms: iOS, tvOS.
Type: `() => void`
The method to call when the user presses the button. You should call [`AppleAuthentication.signInAsync`](#appleauthenticationisavailableasync) in here.
### `style`
Supported platforms: iOS, tvOS.
Optional • Type: StyleProp<[Omit](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys)<[ViewStyle](https://reactnative.dev/docs/view-style-props), 'backgroundColor' | 'borderRadius'\>\>
The custom style to apply to the button. Should not include `backgroundColor` or `borderRadius` properties.
#### Inherited Props
- [ViewProps](https://reactnative.dev/docs/view#props)
## Methods
### `AppleAuthentication.formatFullName(fullName, formatStyle)`
Supported platforms: iOS, tvOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `fullName` | [AppleAuthenticationFullName](#appleauthenticationfullname) | The full name object with the tokenized portions |
| `formatStyle`(optional) | [AppleAuthenticationFullNameFormatStyle](#appleauthenticationfullnameformatstyle) | The style in which the name should be formatted |
Creates a locale-aware string representation of a person's name from an object representing the tokenized portions of a user's full name
Returns: `string`
A locale-aware string representation of a person's name
### `AppleAuthentication.getCredentialStateAsync(user)`
Supported platforms: iOS, tvOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `user` | `string` | The unique identifier for the user whose credential state you'd like to check. This should come from the user field of an [`AppleAuthenticationCredential`](#appleauthenticationcredentialstate) object. |
Queries the current state of a user credential, to determine if it is still valid or if it has been revoked.
> **Note:** This method must be tested on a real device. On the iOS simulator it always throws an error.
Returns: `Promise`
A promise that fulfills with an [`AppleAuthenticationCredentialState`](#appleauthenticationcredentialstate) value depending on the state of the credential.
### `AppleAuthentication.isAvailableAsync()`
Supported platforms: iOS, tvOS.
Determine if the current device's operating system supports Apple authentication.
Returns: `Promise`
A promise that fulfills with `true` if the system supports Apple authentication, and `false` otherwise.
### `AppleAuthentication.refreshAsync(options)`
Supported platforms: iOS, tvOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `options` | [AppleAuthenticationRefreshOptions](#appleauthenticationrefreshoptions) | An [`AppleAuthenticationRefreshOptions`](#appleauthenticationrefreshoptions) object |
An operation that refreshes the logged-in user’s credentials. Calling this method will show the sign in modal before actually refreshing the user credentials.
Returns: `Promise`
A promise that fulfills with an [`AppleAuthenticationCredential`](#appleauthenticationcredential) object after a successful authentication, and rejects with `ERR_REQUEST_CANCELED` if the user cancels the refresh operation.
### `AppleAuthentication.signInAsync(options)`
Supported platforms: iOS, tvOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `options`(optional) | [AppleAuthenticationSignInOptions](#appleauthenticationsigninoptions) | An optional [`AppleAuthenticationSignInOptions`](#appleauthenticationsigninoptions) object |
Sends a request to the operating system to initiate the Apple authentication flow, which will present a modal to the user over your app and allow them to sign in.
You can request access to the user's full name and email address in this method, which allows you to personalize your UI for signed in users. However, users can deny access to either or both of these options at runtime.
Additionally, you will only receive Apple Authentication Credentials the first time users sign into your app, so you must store it for later use. It's best to store this information either server-side, or using [SecureStore](/versions/latest/sdk/securestore), so that the data persists across app installs. You can use [`AppleAuthenticationCredential.user`](#appleauthenticationcredential) to identify the user, since this remains the same for apps released by the same developer.
Returns: `Promise`
A promise that fulfills with an [`AppleAuthenticationCredential`](#appleauthenticationcredential) object after a successful authentication, and rejects with `ERR_REQUEST_CANCELED` if the user cancels the sign-in operation.
### `AppleAuthentication.signOutAsync(options)`
Supported platforms: iOS, tvOS.
| Parameter | Type | Description |
| --- | --- | --- |
| `options` | [AppleAuthenticationSignOutOptions](#appleauthenticationsignoutoptions) | An [`AppleAuthenticationSignOutOptions`](#appleauthenticationsignoutoptions) object |
An operation that ends the authenticated session. Calling this method will show the sign in modal before actually signing the user out.
It is not recommended to use this method to sign out the user as it works counterintuitively. Instead of using this method it is recommended to simply clear all the user's data collected from using [`signInAsync`](#appleauthenticationsigninasyncoptions) or [`refreshAsync`](#appleauthenticationrefreshasyncoptions) methods.
Returns: `Promise`
A promise that fulfills with an [`AppleAuthenticationCredential`](#appleauthenticationcredential) object after a successful authentication, and rejects with `ERR_REQUEST_CANCELED` if the user cancels the sign-out operation.
## Event Subscriptions
### `AppleAuthentication.addRevokeListener(listener)`
Supported platforms: iOS, tvOS.
| Parameter | Type |
| --- | --- |
| `listener` | `() => void` |
Returns: `EventSubscription`
## Interfaces
### `Subscription`
Supported platforms: iOS, tvOS.
A subscription object that allows to conveniently remove an event listener from the emitter.
Subscription Methods
### `remove()`
Supported platforms: iOS, tvOS.
Removes an event listener for which the subscription has been created. After calling this function, the listener will no longer receive any events from the emitter.
Returns: `void`
## Types
### `AppleAuthenticationCredential`
Supported platforms: iOS, tvOS.
The object type returned from a successful call to [`AppleAuthentication.signInAsync()`](#appleauthenticationsigninasyncoptions), [`AppleAuthentication.refreshAsync()`](#appleauthenticationrefreshasyncoptions), or [`AppleAuthentication.signOutAsync()`](#appleauthenticationsignoutasyncoptions) which contains all of the pertinent user and credential information.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidcredential) for more details.
| Property | Type | Description |
| --- | --- | --- |
| authorizationCode | `string | null` | A short-lived session token used by your app for proof of authorization when interacting with the app's server counterpart. Unlike `user`, this is ephemeral and will change each session. |
| email | `string | null` | The user's email address. Might not be present if you didn't request the `EMAIL` scope. May also be null if this is not the first time the user has signed into your app. If the user chose to withhold their email address, this field will instead contain an obscured email address with an Apple domain. |
| fullName | [AppleAuthenticationFullName](#appleauthenticationfullname) | null | The user's name. May be `null` or contain `null` values if you didn't request the `FULL_NAME` scope, if the user denied access, or if this is not the first time the user has signed into your app. |
| identityToken | `string | null` | A JSON Web Token (JWT) that securely communicates information about the user to your app. |
| realUserStatus | [AppleAuthenticationUserDetectionStatus](#appleauthenticationuserdetectionstatus) | A value that indicates whether the user appears to the system to be a real person. |
| state | `string | null` | An arbitrary string that your app provided as `state` in the request that generated the credential. Used to verify that the response was from the request you made. Can be used to avoid replay attacks. If you did not provide `state` when making the sign-in request, this field will be `null`. |
| user | `string` | An identifier associated with the authenticated user. You can use this to check if the user is still authenticated later. This is stable and can be shared across apps released under the same development team. The same user will have a different identifier for apps released by other developers. |
### `AppleAuthenticationFullName`
Supported platforms: iOS, tvOS.
An object representing the tokenized portions of the user's full name. Any of all of the fields may be `null`. Only applicable fields that the user has allowed your app to access will be nonnull.
| Property | Type | Description |
| --- | --- | --- |
| familyName | `string | null` | - |
| givenName | `string | null` | - |
| middleName | `string | null` | - |
| namePrefix | `string | null` | - |
| nameSuffix | `string | null` | - |
| nickname | `string | null` | - |
### `AppleAuthenticationFullNameFormatStyle`
Supported platforms: iOS, tvOS.
Literal Type: `string`
A value to specify the style for formatting a name.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/foundation/personnamecomponentsformatter) for more details.
Acceptable values are: `'default'` | `'short'` | `'medium'` | `'long'` | `'abbreviated'`
### `AppleAuthenticationRefreshOptions`
Supported platforms: iOS, tvOS.
The options you can supply when making a call to [`AppleAuthentication.refreshAsync()`](#appleauthenticationrefreshasyncoptions). You must include the ID string of the user whose credentials you'd like to refresh.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest) for more details.
| Property | Type | Description |
| --- | --- | --- |
| requestedScopes(optional) | [AppleAuthenticationScope[]](#appleauthenticationscope) | Array of user information scopes to which your app is requesting access. Note that the user can choose to deny your app access to any scope at the time of logging in. You will still need to handle `null` values for any scopes you request. Additionally, note that the requested scopes will only be provided to you the first time each user signs into your app; in subsequent requests they will be `null`. Defaults to `[]` (no scopes). |
| state(optional) | `string` | An arbitrary string that is returned unmodified in the corresponding credential after a successful authentication. This can be used to verify that the response was from the request you made and avoid replay attacks. More information on this property is available in the OAuth 2.0 protocol [RFC6749](https://tools.ietf.org/html/rfc6749#section-10.12). |
| user | `string` | - |
### `AppleAuthenticationSignInOptions`
Supported platforms: iOS, tvOS.
The options you can supply when making a call to [`AppleAuthentication.signInAsync()`](#appleauthenticationsigninasyncoptions). None of these options are required.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest) for more details.
| Property | Type | Description |
| --- | --- | --- |
| nonce(optional) | `string` | An arbitrary string that is used to prevent replay attacks. See more information on this in the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps). |
| requestedScopes(optional) | [AppleAuthenticationScope[]](#appleauthenticationscope) | Array of user information scopes to which your app is requesting access. Note that the user can choose to deny your app access to any scope at the time of logging in. You will still need to handle `null` values for any scopes you request. Additionally, note that the requested scopes will only be provided to you the first time each user signs into your app; in subsequent requests they will be `null`. Defaults to `[]` (no scopes). |
| state(optional) | `string` | An arbitrary string that is returned unmodified in the corresponding credential after a successful authentication. This can be used to verify that the response was from the request you made and avoid replay attacks. More information on this property is available in the OAuth 2.0 protocol [RFC6749](https://tools.ietf.org/html/rfc6749#section-10.12). |
### `AppleAuthenticationSignOutOptions`
Supported platforms: iOS, tvOS.
The options you can supply when making a call to [`AppleAuthentication.signOutAsync()`](#appleauthenticationsignoutasyncoptions). You must include the ID string of the user to sign out.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationopenidrequest) for more details.
| Property | Type | Description |
| --- | --- | --- |
| state(optional) | `string` | An arbitrary string that is returned unmodified in the corresponding credential after a successful authentication. This can be used to verify that the response was from the request you made and avoid replay attacks. More information on this property is available in the OAuth 2.0 protocol [RFC6749](https://tools.ietf.org/html/rfc6749#section-10.12). |
| user | `string` | - |
## Enums
### `AppleAuthenticationButtonStyle`
Supported platforms: iOS, tvOS.
An enum whose values control which pre-defined color scheme to use when rendering an [`AppleAuthenticationButton`](#appleauthenticationbutton).
#### `WHITE`
`AppleAuthenticationButtonStyle.WHITE = 0`
White button with black text.
#### `WHITE_OUTLINE`
`AppleAuthenticationButtonStyle.WHITE_OUTLINE = 1`
White button with a black outline and black text.
#### `BLACK`
`AppleAuthenticationButtonStyle.BLACK = 2`
Black button with white text.
### `AppleAuthenticationButtonType`
Supported platforms: iOS, tvOS.
An enum whose values control which pre-defined text to use when rendering an [`AppleAuthenticationButton`](#appleauthenticationbutton).
#### `SIGN_IN`
`AppleAuthenticationButtonType.SIGN_IN = 0`
"Sign in with Apple"
#### `CONTINUE`
`AppleAuthenticationButtonType.CONTINUE = 1`
"Continue with Apple"
#### `SIGN_UP`
Supported platforms: iOS 13.2+.
`AppleAuthenticationButtonType.SIGN_UP = 2`
"Sign up with Apple"
### `AppleAuthenticationCredentialState`
Supported platforms: iOS, tvOS.
An enum whose values specify state of the credential when checked with [`AppleAuthentication.getCredentialStateAsync()`](#appleauthenticationgetcredentialstateasyncuser).
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidprovidercredentialstate) for more details.
#### `REVOKED`
`AppleAuthenticationCredentialState.REVOKED = 0`
#### `AUTHORIZED`
`AppleAuthenticationCredentialState.AUTHORIZED = 1`
#### `NOT_FOUND`
`AppleAuthenticationCredentialState.NOT_FOUND = 2`
#### `TRANSFERRED`
`AppleAuthenticationCredentialState.TRANSFERRED = 3`
### `AppleAuthenticationOperation`
Supported platforms: iOS, tvOS.
#### `IMPLICIT`
`AppleAuthenticationOperation.IMPLICIT = 0`
An operation that depends on the particular kind of credential provider.
#### `LOGIN`
`AppleAuthenticationOperation.LOGIN = 1`
#### `REFRESH`
`AppleAuthenticationOperation.REFRESH = 2`
#### `LOGOUT`
`AppleAuthenticationOperation.LOGOUT = 3`
### `AppleAuthenticationScope`
Supported platforms: iOS, tvOS.
An enum whose values specify scopes you can request when calling [`AppleAuthentication.signInAsync()`](#appleauthenticationsigninasyncoptions).
> Note that it is possible that you will not be granted all of the scopes which you request. You will still need to handle null values for any fields you request.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asauthorizationscope) for more details.
#### `FULL_NAME`
`AppleAuthenticationScope.FULL_NAME = 0`
#### `EMAIL`
`AppleAuthenticationScope.EMAIL = 1`
### `AppleAuthenticationUserDetectionStatus`
Supported platforms: iOS, tvOS.
An enum whose values specify the system's best guess for how likely the current user is a real person.
> **See:** [Apple Documentation](https://developer.apple.com/documentation/authenticationservices/asuserdetectionstatus) for more details.
#### `UNSUPPORTED`
`AppleAuthenticationUserDetectionStatus.UNSUPPORTED = 0`
The system does not support this determination and there is no data.
#### `UNKNOWN`
`AppleAuthenticationUserDetectionStatus.UNKNOWN = 1`
The system has not determined whether the user might be a real person.
#### `LIKELY_REAL`
`AppleAuthenticationUserDetectionStatus.LIKELY_REAL = 2`
The user appears to be a real person.
## 错误代码
大多数错误代码与官方 [Apple Authorization errors](https://developer.apple.com/documentation/authenticationservices/asauthorizationerror/code) 相匹配。
| 代码 | 描述 |
| --- | --- |
| ERR_INVALID_OPERATION | 已执行无效的授权操作。 |
| ERR_INVALID_RESPONSE | 授权请求收到了无效响应。 |
| ERR_INVALID_SCOPE | 传入了无效的 [`AppleAuthenticationScope`](/versions/latest/sdk/apple-authentication#appleauthenticationscope)。 |
| ERR_REQUEST_CANCELED | 用户取消了授权尝试。 |
| ERR_REQUEST_FAILED | 授权尝试失败。有关附加信息,请参阅错误消息。 |
| ERR_REQUEST_NOT_HANDLED | 授权请求未被正确处理。 |
| ERR_REQUEST_NOT_INTERACTIVE | 授权请求不是交互式的。 |
| ERR_REQUEST_UNKNOWN | 授权尝试因未知原因失败。 |
---
---
title: 应用程序
description: 一个通用库,可在运行时提供有关原生应用程序的 ID、应用名称和构建版本的信息。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-application'
packageName: 'expo-application'
platforms: ['android', 'ios', 'web', 'tvos', 'expo-go']
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/application/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo 应用程序
一个通用库,可在运行时提供有关原生应用程序的 ID、应用名称和构建版本的信息。
Android, iOS, tvOS, Web, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo-application` 在运行时提供有关原生应用的 ID、应用名称和构建版本的有用信息。
## 安装
```sh
npx expo install expo-application
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## API
```js
import * as Application from 'expo-application';
```
## Constants
### `Application.applicationId`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string | null`
The ID of the application. On Android, this is the application ID. On iOS, this is the bundle ID. On web, this is `null`.
Example
`"com.cocoacasts.scribbles"`, `"com.apple.Pages"`
### `Application.applicationName`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string | null`
The human-readable name of the application that is displayed with the app's icon on the device's home screen or desktop. On Android and iOS, this value is a `string` unless the name could not be retrieved, in which case this value will be `null`. On web this value is `null`.
Example
`"Expo"`, `"Yelp"`, `"Instagram"`
### `Application.nativeApplicationVersion`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string | null`
The human-readable version of the native application that may be displayed in the app store. At time when native app is built, on Android, this is the version name set by `version` in app config, and on iOS, the `Info.plist` value for `CFBundleShortVersionString`. On web, this value is `null`.
Example
`"2.11.0"`
### `Application.nativeBuildVersion`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string | null`
The internal build version of the native application that the app stores may use to distinguish between different binaries. At the time when native app is built, On Android, this is the version code set by `android.versionCode` in app config, and on iOS, the `Info.plist` value for `CFBundleVersion` (set with `ios.buildNumber` value in app config in a standalone app). On web, this value is `null`. The return type on Android and iOS is `string`.
Example
`"114"`
## Methods
### `Application.getAndroidId()`
Supported platforms: Android.
Gets the value of [`Settings.Secure.ANDROID_ID`](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID). This is a hexadecimal `string` unique to each combination of app-signing key, user, and device. The value may change if a factory reset is performed on the device or if an APK signing key changes. For more information about how the platform handles `ANDROID_ID` in Android 8.0 (API level 26) and higher, see [Android 8.0 Behavior Changes](https://developer.android.com/about/versions/oreo/android-8.0-changes.html#privacy-all). On iOS and web, this function is unavailable.
> In versions of the platform lower than Android 8.0 (API level 26), this value remains constant for the lifetime of the user's device. See the [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID) official docs for more information.
Returns: `string`
Example
```ts
Application.getAndroidId();
// "dd96dec43fb81c97"
```
### `Application.getInstallationTimeAsync()`
Supported platforms: Android, iOS, tvOS, Web.
Gets the time the app was installed onto the device, not counting subsequent updates. If the app is uninstalled and reinstalled, this method returns the time the app was reinstalled.
- On Android, this method uses [`PackageInfo.firstInstallTime`](https://developer.android.com/reference/android/content/pm/PackageInfo.html#firstInstallTime).
- On iOS, this method uses the [`NSFileCreationDate`](https://developer.apple.com/documentation/foundation/nsfilecreationdate?language=objc) of the app's document root directory.
- On web, this method returns `null`.
Returns: `Promise`
A `Promise` that fulfills with a `Date` object that specifies the time the app was installed on the device.
Example
```ts
await Application.getInstallationTimeAsync();
// 2019-07-18T18:08:26.121Z
```
### `Application.getInstallReferrerAsync()`
Supported platforms: Android.
Gets the referrer URL of the installed app with the [`Install Referrer API`](https://developer.android.com/google/play/installreferrer) from the Google Play Store. In practice, the referrer URL may not be a complete, absolute URL.
Returns: `Promise`
A `Promise` that fulfills with a `string` of the referrer URL of the installed app.
Example
```ts
await Application.getInstallReferrerAsync();
// "utm_source=google-play&utm_medium=organic"
```
### `Application.getIosApplicationReleaseTypeAsync()`
Supported platforms: iOS.
Gets the iOS application release type.
Returns: `Promise`
A `Promise` which fulfills with an [`ApplicationReleaseType`](#applicationreleasetype).
### `Application.getIosIdForVendorAsync()`
Supported platforms: iOS.
Gets the iOS "identifier for vendor" ([IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor)) value, a string ID that uniquely identifies a device to the app’s vendor. This method may sometimes return `nil`, in which case wait and call the method again later. This might happen when the device has been restarted before the user has unlocked the device.
The OS will change the vendor identifier if all apps from the current app's vendor have been uninstalled.
Returns: `Promise`
A `Promise` that fulfills with a `string` specifying the app's vendor ID. Apps from the same vendor will return the same ID. See Apple's documentation for more information about the vendor ID's semantics.
Example
```ts
await Application.getIosIdForVendorAsync();
// "68753A44-4D6F-1226-9C60-0050E4C00067"
```
### `Application.getIosPushNotificationServiceEnvironmentAsync()`
Supported platforms: iOS.
Gets the current [Apple Push Notification (APN)](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment?language=objc) service environment.
Returns: `Promise`
A `Promise` that fulfills with the string, either `'development'` or `'production'`, based on the current APN environment, or `null` on the simulator as it does not support registering with APNs.
### `Application.getLastUpdateTimeAsync()`
Supported platforms: Android.
Gets the last time the app was updated from the Google Play Store.
Returns: `Promise`
A `Promise` that fulfills with a `Date` object that specifies the last time the app was updated via the Google Play Store.
Example
```ts
await Application.getLastUpdateTimeAsync();
// 2019-07-18T21:20:16.887Z
```
## Types
### `PushNotificationServiceEnvironment`
Supported platforms: iOS.
Literal Type: `union`
Maps to the [`aps-environment`](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment) key in the native target's registered entitlements.
Acceptable values are: `'development'` | `'production'` | `null`
## Enums
### `ApplicationReleaseType`
Supported platforms: iOS.
#### `UNKNOWN`
`ApplicationReleaseType.UNKNOWN = 0`
#### `SIMULATOR`
`ApplicationReleaseType.SIMULATOR = 1`
#### `ENTERPRISE`
`ApplicationReleaseType.ENTERPRISE = 2`
#### `DEVELOPMENT`
`ApplicationReleaseType.DEVELOPMENT = 3`
#### `AD_HOC`
`ApplicationReleaseType.AD_HOC = 4`
#### `APP_STORE`
`ApplicationReleaseType.APP_STORE = 5`
## 错误代码
| Code | Description |
| --- | --- |
| `ERR_APPLICATION_PACKAGE_NAME_NOT_FOUND` | 由 `getInstallationTimeAsync` 和 `getLastUpdateTimeAsync` 抛出的错误代码。如果无法检索包信息或包名,可能会抛出此错误。 |
| `ERR_APPLICATION_INSTALL_REFERRER_UNAVAILABLE` | 当前的 Play Store 应用不提供 installation referrer API,或者可能未安装 Play Store。在某些默认未预装 Play Store 的 AVD 上测试时可能会出现此错误,例如 Google Pixel 3 和 Nexus 6。 |
| `ERR_APPLICATION_INSTALL_REFERRER_CONNECTION` | 无法与 Google Play Store 建立连接。 |
| `ERR_APPLICATION_INSTALL_REFERRER_REMOTE_EXCEPTION` | 在与 Play Store 建立连接后抛出了 `RemoteException`。如果托管远程对象的进程不再可用,就可能发生这种情况,通常意味着该进程崩溃了。有关更多信息,请参阅 [关于 `RemoteException` 的这个 StackOverflow 回答](https://stackoverflow.com/questions/3156389/android-remoteexceptions-and-services)。 |
| `ERR_APPLICATION_INSTALL_REFERRER` | `getInstallReferrerAsync` 方法的通用默认错误代码。如果在获取 install referrer 时发生异常,但该异常不是更精确的错误之一,就会抛出此错误代码。错误信息中会提供 [`responseCode`](https://developer.android.com/reference/com/android/installreferrer/api/InstallReferrerClient.InstallReferrerResponse.html)。 |
| `ERR_APPLICATION_INSTALL_REFERRER_SERVICE_DISCONNECTED` | 与 install referrer 服务的连接已丢失。当尝试连接并设置 install referrer 服务,但连接丢失时会抛出此错误。有关更多信息,请参阅 [Android 文档](https://developer.android.com/reference/com/android/installreferrer/api/InstallReferrerStateListener)。 |
---
---
title: 资源
description: 一个通用库,允许下载资源并将其与其他库一起使用。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-asset'
packageName: 'expo-asset'
platforms: ['android', 'ios', 'tvos', 'web', 'expo-go']
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/asset/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo 资源
一个通用库,允许下载资源并将其与其他库一起使用。
Android, iOS, tvOS, Web, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo-asset` 提供了一个用于访问 Expo 资源系统的接口。资源是与应用源代码放在一起、且应用在运行时需要的任何文件。示例包括图片、字体和声音。Expo 的资源系统与 React Native 的资源系统集成,因此你可以使用 `require('path/to/file')` 来引用文件。例如,这也是你在 React Native 中引用静态图片文件并将其用于 `Image` 组件的方式。更多信息请查看 React Native 关于[静态图片资源的文档](https://reactnative.dev/docs/images#static-image-resources)。这种引用静态图片资源的方法在 Expo 中开箱即用。
## 安装
```sh
npx expo install expo-asset
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## app 配置中的配置
如果你的项目使用配置插件([Continuous Native Generation (CNG)](/workflow/continuous-native-generation)),你可以使用 `expo-asset` 内置的 [config plugin](/config-plugins/introduction) 来进行配置。该插件允许你配置一些无法在运行时设置、且需要构建新的应用二进制文件后才会生效的属性。如果你的应用**不**使用 CNG,那么你需要手动配置该库。
### Example app.json with config plugin
```json
{
"expo": {
"plugins": [
[
"expo-asset",
{
"assets": ["path/to/file.png", "path/to/directory"]
}
]
]
}
}
```
### Configurable properties
| Name | Default | Description |
| --- | --- | --- |
| `assets` | `[]` | 要链接到原生项目的资源文件或目录数组。路径应相对于项目根目录,这样无论是直接指定还是通过目录指定,文件名都会成为资源名称。 . 支持的文件类型:
- 图片:`.png`、`.jpg`、`.gif`
- 媒体:`.mp4`、`.mp3`、`.lottie`、`.riv`
- SQLite 数据库文件:`.db`
注意:要导入现有数据库文件(.db),请参阅 SQLite API 参考 中的说明。对于其他文件类型(例如 .lottie 或 .riv),请参阅 如何在 metro 配置中向 assetExts 添加文件扩展名。 |
### 用法
了解更多关于如何使用 `expo-asset` config plugin 将资源文件嵌入到项目中的内容,请参阅[构建时加载资源](/develop/user-interface/assets#load-an-asset-at-build-time)。
## API
```js
import { Asset } from 'expo-asset';
```
## Hooks
### `useAssets(moduleIds)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type |
| --- | --- |
| `moduleIds` | `number | number[]` |
Downloads and stores one or more assets locally. After the assets are loaded, this hook returns a list of asset instances. If something went wrong when loading the assets, an error is returned.
> Note, the assets are not "reloaded" when you dynamically change the asset list.
Returns: `[Asset[] | undefined, Error | undefined]`
Returns an array containing:
- on the first position, a list of all loaded assets. If they aren't loaded yet, this value is `undefined`.
- on the second position, an error which encountered when loading the assets. If there was no error, this value is `undefined`.
Example
```tsx
const [assets, error] = useAssets([require('path/to/asset.jpg'), require('path/to/other.png')]);
return assets ? : null;
```
## Classes
### `Asset`
Supported platforms: Android, iOS, tvOS, Web.
The `Asset` class represents an asset in your app. It gives metadata about the asset (such as its name and type) and provides facilities to load the asset data.
Asset Properties
### `downloaded`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean` • Default: `false`
Whether the asset has finished downloading from a call to [`downloadAsync()`](#downloadasync).
### `hash`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Literal type: `union` • Default: `null`
The MD5 hash of the asset's data.
Acceptable values are: `string` | `null`
### `height`
Supported platforms: Android, iOS, tvOS, Web.
Literal type: `union` • Default: `null`
If the asset is an image, the height of the image data divided by the scale factor. The scale factor is the number after `@` in the filename, or `1` if not present.
Acceptable values are: `number` | `null`
### `localUri`
Supported platforms: Android, iOS, tvOS, Web.
Literal type: `union` • Default: `null`
If the asset has been downloaded (by calling [`downloadAsync()`](#downloadasync)), the `file://` URI pointing to the local file on the device that contains the asset data.
Acceptable values are: `string` | `null`
### `name`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string`
The name of the asset file without the extension. Also without the part from `@` onward in the filename (used to specify scale factor for images).
### `type`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Type: `string`
The extension of the asset filename.
### `uri`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Type: `string`
A URI that points to the asset's data on the remote server. When running the published version of your app, this refers to the location on Expo's asset server where Expo has stored your asset. When running the app from Expo CLI during development, this URI points to Expo CLI's server running on your computer and the asset is served directly from your computer. If you are not using Classic Updates (legacy), this field should be ignored as we ensure your assets are on device before running your application logic.
### `width`
Supported platforms: Android, iOS, tvOS, Web.
Literal type: `union` • Default: `null`
If the asset is an image, the width of the image data divided by the scale factor. The scale factor is the number after `@` in the filename, or `1` if not present.
Acceptable values are: `number` | `null`
Asset Methods
### `downloadAsync()`
Supported platforms: Android, iOS, tvOS, Web.
Downloads the asset data to a local file in the device's cache directory. Once the returned promise is fulfilled without error, the [`localUri`](#localuri) field of this asset points to a local file containing the asset data. The asset is only downloaded if an up-to-date local file for the asset isn't already present due to an earlier download. The downloaded `Asset` will be returned when the promise is resolved.
> **Note:** There is no guarantee that files downloaded via `downloadAsync` persist between app sessions. `downloadAsync` stores files in the caches directory, so it's up to the OS to clear this folder at its own discretion or when the user manually purges the caches directory. Downloaded assets are stored as `ExponentAsset-{cacheFileId}.{extension}` within the cache directory. To manually clear cached assets, you can use [`expo-file-system`](/versions/latest/sdk/filesystem) to delete the cache directory: `Paths.cache.delete()` or use the legacy API `deleteAsync(cacheDirectory)`.
Returns: `Promise`
Returns a Promise which fulfills with an `Asset` instance.
### `fromMetadata(meta)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type |
| --- | --- |
| `meta` | [AssetMetadata](#assetmetadata) |
Returns: `Asset`
### `fromModule(virtualAssetModule)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `virtualAssetModule` | `string | number | { height: number, uri: string, width: number }` | The value of `require('path/to/file')` for the asset or external network URL |
Returns the [`Asset`](#asset) instance representing an asset given its module or URL.
Returns: `Asset`
The [`Asset`](#asset) instance for the asset.
### `fromURI(uri)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type |
| --- | --- |
| `uri` | `string` |
Returns: `Asset`
### `loadAsync(moduleId)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `moduleId` | `string | number | number[] | string[]` | An array of `require('path/to/file')` or external network URLs. Can also be just one module or URL without an Array. |
A helper that wraps `Asset.fromModule(module).downloadAsync` for convenience.
Returns: `Promise`
Returns a Promise that fulfills with an array of `Asset`s when the asset(s) has been saved to disk.
Example
```ts
const [{ localUri }] = await Asset.loadAsync(require('./assets/snack-icon.png'));
```
## Types
### `AssetDescriptor`
Supported platforms: Android, iOS, tvOS, Web.
| Property | Type | Description |
| --- | --- | --- |
| hash(optional) | `string | null` | - |
| height(optional) | `number | null` | - |
| name | `string` | - |
| type | `string` | - |
| uri | `string` | - |
| width(optional) | `number | null` | - |
### `AssetMetadata`
Supported platforms: Android, iOS, tvOS, Web.
Type: [Pick](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)<[PackagerAsset](https://github.com/facebook/react-native/blob/main/packages/assets/registry.js), 'httpServerLocation' | 'name' | 'hash' | 'type' | 'scales' | 'width' | 'height'\> extended by:
| Property | Type | Description |
| --- | --- | --- |
| fileHashes(optional) | `string[]` | - |
| fileUris(optional) | `string[]` | - |
| uri(optional) | `string` | - |
---
---
title: '@react-native-async-storage/async-storage'
description: 一个提供异步、未加密、持久化的键值存储 API 的库。
sourceCodeUrl: 'https://github.com/react-native-async-storage/async-storage'
packageName: '@react-native-async-storage/async-storage'
platforms: ['android', 'ios', 'tvos', 'macos', 'web', 'expo-go']
inExpoGo: true
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/async-storage/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# @react-native-async-storage/async-storage
一个提供异步、未加密、持久化的键值存储 API 的库。
Android, iOS, macOS, tvOS, Web, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
Async Storage 是一种异步、未加密、持久化的键值存储解决方案。
## 安装
```sh
npx expo install @react-native-async-storage/async-storage
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project. Then, follow the [installation instructions](https://react-native-async-storage.github.io/2.0/Installation/) provided in the library's README or documentation.
## 了解更多
[访问官方文档](https://react-native-async-storage.github.io/2.0/Usage/) — 获取有关 API 及其用法的完整信息。
---
---
title: 音频(expo-audio)
description: 一个提供 API 用于在应用中实现音频播放和录制的库。
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-audio'
packageName: 'expo-audio'
iconUrl: '/static/images/packages/expo-av.png'
platforms: ['android', 'ios', 'web', 'tvos', 'expo-go']
---
## Submitting Feedback
If this page contains errors, outdated information, or gaps that blocked you from completing a task, report it so the docs can be improved:
curl -X POST https://api.expo.dev/v2/feedback/docs-send -H 'Content-Type: application/json' -d '{"url":"/versions/latest/sdk/audio/","feedback":"🤖 Agent feedback: "}'
Only submit when you have something specific and actionable to report.
# Expo 音频(expo-audio)
一个提供 API 用于在应用中实现音频播放和录制的库。
Android, iOS, tvOS, Web, Included in Expo Go
> For the complete documentation index, see [llms.txt](/llms.txt). Use this Use this file to discover all available pages.
`expo-audio` 是一个跨平台音频库,用于访问设备的原生音频能力。
[Android 媒体格式支持文档](https://developer.android.com/media/media3/exoplayer/supported-formats)涵盖了在 Android 上使用 Expo Player 时支持的格式。[iOS 音频和视频格式文档](https://developer.apple.com/documentation/coreaudiotypes/audio-format-identifiers)列出了 Apple 设备支持的媒体格式。
请注意,如果耳机/Bluetooth 音频设备断开连接,音频会自动停止。
## 安装
```sh
npx expo install expo-audio
```
If you are installing this in an [existing React Native app](/bare/overview), make sure to [install `expo`](/bare/installing-expo-modules) in your project.
## 在 app config 中配置
如果你在项目中使用 config plugins([Continuous Native Generation (CNG)](/workflow/continuous-native-generation)),可以使用 `expo-audio` 内置的 [config plugin](/config-plugins/introduction) 进行配置。该插件允许你配置一些无法在运行时设置、且需要重新构建新的应用二进制文件才会生效的属性。如果你的应用**不**使用 CNG,那么你需要手动配置该库。
### Example app.json with config plugin
```json
{
"expo": {
"plugins": [
[
"expo-audio",
{
"microphonePermission": "允许 $(PRODUCT_NAME) 访问你的麦克风。",
"enableBackgroundPlayback": true,
"enableBackgroundRecording": false
}
]
]
}
}
```
### Configurable properties
| Name | Default | Description |
| --- | --- | --- |
| `microphonePermission` | `"允许 $(PRODUCT_NAME) 访问你的麦克风"` | Only for: iOS. 用于设置 `NSMicrophoneUsageDescription` 权限消息的字符串。将其设为 `false` 会禁用该权限。 |
| `recordAudioAndroid` | `true` | Only for: Android. 一个布尔值,用于决定是否在 Android 上启用 `RECORD_AUDIO` 权限。 |
| `enableBackgroundRecording` | `false` | 一个布尔值,用于决定是否启用后台音频录制。在 Android 上,这会添加录制前台服务和权限,并在录制期间显示一条持续存在的通知。在 iOS 上,这会添加 `audio` 后台模式。\*\*注意:\*\*后台录制可能会显著影响电池续航。 |
| `enableBackgroundPlayback` | `true` | 一个布尔值,用于决定是否启用后台音频播放。在 Android 上,这会添加媒体播放前台服务,并允许你显示锁屏控制,这是持续后台播放所必需的。在 iOS 上,这会添加 `audio` 后台模式。 |
## 用法
### 播放声音
```jsx
import { View, StyleSheet, Button } from 'react-native';
import { useAudioPlayer } from 'expo-audio';
const audioSource = require('./assets/Hello.mp3');
export default function App() {
const player = useAudioPlayer(audioSource);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
```
### 录制声音
```jsx
import { useState, useEffect } from 'react';
import { View, StyleSheet, Button } from 'react-native';
import {
useAudioRecorder,
AudioModule,
RecordingPresets,
setAudioModeAsync,
useAudioRecorderState,
} from 'expo-audio';
export default function App() {
const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
const recorderState = useAudioRecorderState(audioRecorder);
const record = async () => {
await audioRecorder.prepareToRecordAsync();
audioRecorder.record();
};
const stopRecording = async () => {
// 录音文件将可通过 `audioRecorder.uri` 获取。
await audioRecorder.stop();
};
useEffect(() => {
(async () => {
const status = await AudioModule.requestRecordingPermissionsAsync();
if (!status.granted) {
Alert.alert('访问麦克风的权限被拒绝');
}
setAudioModeAsync({
playsInSilentMode: true,
allowsRecording: true,
});
})();
}, []);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
```
### 在后台播放音频
后台音频播放允许你的应用在进入后台或设备屏幕锁定时继续播放音频。
#### 配置
要启用后台音频播放,请在你的 [app config](/workflow/configuration) 中使用 config plugin:
```json
{
"expo": {
"plugins": [
[
"expo-audio",
{
"enableBackgroundPlayback": true
}
]
]
}
}
```
上述配置会自动配置所需的原生设置:
- Android 添加 `FOREGROUND_SERVICE` 和 `FOREGROUND_SERVICE_MEDIA_PLAYBACK` 权限。同时在应用的 **AndroidManifest.xml** 中声明一个媒体播放前台服务 (`AudioControlsService`)。
- iOS 添加 `audio` `UIBackgroundMode` 能力
#### 用法
在使用 config plugin 配置完应用后,你需要:
1. **配置音频会话** 以允许后台播放
2. **启用锁屏控制**(在 Android 上持续后台播放是必需的)
```jsx
import { View, Button } from 'react-native';
import { useAudioPlayer, setAudioModeAsync } from 'expo-audio';
import { useEffect } from 'react';
export default function AudioPlayerScreen() {
const audioSource = require('./assets/audio.mp3');
const player = useAudioPlayer(audioSource);
useEffect(() => {
// 为后台播放配置音频会话
setAudioModeAsync({
playsInSilentMode: true,
shouldPlayInBackground: true,
interruptionMode: 'doNotMix',
});
}, []);
const handlePlay = () => {
// 使用元数据启用锁屏控制
player.setActiveForLockScreen(true, {
title: '我的音频标题',
artist: '艺人名称',
albumTitle: '专辑名称',
artworkUrl: 'https://example.com/artwork.jpg', // 可选
});
// 开始播放 - 这将继续在后台运行
player.play();
};
const handleStop = () => {
player.pause();
// 可选:完成后禁用锁屏控制
player.setActiveForLockScreen(false);
};
return (
);
}
```
Android
> **注意**:在 Android 上,你必须使用 [`setActiveForLockScreen`](/versions/latest/sdk/audio#setactiveforlockscreenactive-metadata-options) 启用锁屏控制,才能实现持续后台播放。否则,音频将在大约 3 分钟的后台播放后停止(这是操作系统限制)。请确保正确地[配置 config plugin](/versions/latest/sdk/audio#configuration-in-app-config)。
- 通知栏中会出现带有播放控制的媒体通知
- 音频会在后台无限期播放
- 用户可以通过锁屏和通知控制播放
- 前台服务会在播放期间保持播放进程存活
iOS
在 iOS 上,一旦音频会话配置为 `shouldPlayInBackground: true`,音频播放就会在后台无缝继续。锁屏控制是可选的,但它们通过在锁屏和控制中心提供播放控制来提升用户体验。
Are you using this library in an existing React Native app?
如果你没有使用 Continuous Native Generation([CNG](/workflow/continuous-native-generation))(也就是你在手动使用原生 **android** 和 **ios** 项目),那么你需要为后台播放配置以下内容:
- 对于 Android,添加到 **android/app/src/main/AndroidManifest.xml**:
```xml
```
- 对于 iOS,添加到 **ios/YourApp/Info.plist**:
```xml
UIBackgroundModesaudio
```
### 在后台录制音频
> **警告** 后台录制可能会显著影响电池续航。仅在你的应用功能确实需要时才启用它。
后台音频录制允许你的应用在进入后台或设备屏幕锁定时继续录制。
要启用后台录制,请在你的 [app config](/workflow/configuration) 中使用 config plugin:
```json
{
"expo": {
"plugins": [
[
"expo-audio",
{
"microphonePermission": "允许 $(PRODUCT_NAME) 录制音频。",
"enableBackgroundRecording": true
}
]
]
}
}
```
上述配置会自动配置所需的原生设置:
- Android 添加 `FOREGROUND_SERVICE`, `FOREGROUND_SERVICE_MICROPHONE` 和 `POST_NOTIFICATIONS` 权限。同时在应用的 **AndroidManifest.xml** 中声明一个音频 录制前台服务。
- iOS 添加 `audio` `UIBackgroundMode` 能力
Are you using this library in an existing React Native app?
如果你没有使用 Continuous Native Generation([CNG](/workflow/continuous-native-generation))(也就是你在手动使用原生 **android** 和 **ios** 项目),那么你需要在原生项目中配置以下权限:
- 对于 Android,添加到 **android/app/src/main/AndroidManifest.xml**:
```xml
```
- 对于 iOS,添加到 **ios/YourApp/Info.plist**:
```xml
UIBackgroundModesaudio
```
#### 用法
配置完应用后,可在运行时使用 [`setAudioModeAsync`](/versions/latest/sdk/audio#audiosetaudiomodeasyncmode) 启用后台录制:
```jsx
import { setAudioModeAsync, useAudioRecorder, RecordingPresets } from 'expo-audio';
await setAudioModeAsync({
playsInSilentMode: true,
allowsRecording: true,
allowsBackgroundRecording: true,
});
const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
await recorder.prepareToRecordAsync();
await recorder.record();
// 录音会在后台继续
```
Android
在 Android 上,后台录制需要前台服务,它会显示一条带有“正在录制音频”文本和停止按钮的持续通知。录制进行时,这条通知无法被关闭,录制停止后会自动消失。
iOS
在 iOS 上,当应用处于后台或屏幕锁定时,后台录制会无缝继续。除系统状态栏之外,不会向应用用户显示任何额外通知或指示。
### 直接使用 AudioPlayer
在大多数情况下,请使用 [`useAudioPlayer`](/versions/latest/sdk/audio#useaudioplayersource-options) 钩子来创建 `AudioPlayer` 实例。它会管理播放器的生命周期,并在组件卸载时确保正确释放。不过,在某些高级用例中,你可能需要创建一个超出组件生命周期仍然存在的 `AudioPlayer`。 在这种情况下,请使用 [`createAudioPlayer`](/versions/latest/sdk/audio#audiocreateaudioplayersource-options) 函数。你需要了解这种方式带来的风险,因为当播放器不再需要时,调用 [`release()`](/versions/latest/sdk/expo#release) 方法是你的责任。如果处理不当,这种方式可能导致内存泄漏。
```tsx
import { createAudioPlayer } from 'expo-audio';
const player = createAudioPlayer(audioSource);
```
### Web 使用说明
- Chrome 上的一个 MediaRecorder 问题会生成缺少时长元数据的 WebM 文件。[查看公开的 Chromium 问题](https://bugs.chromium.org/p/chromium/issues/detail?id=642012)。
- MediaRecorder 的编码选项和其他配置在不同浏览器之间并不一致。在你的应用中使用诸如 [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) 或 [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) 这样的 polyfill 会改善你的体验。传递给 `prepareToRecordAsync` 的任何选项都会直接传递给 MediaRecorder API,因此也会传递给 polyfill。
- Web 浏览器要求站点必须通过安全方式提供,才能监听麦克风。更多详情请参见 [MediaDevices `getUserMedia()` security](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#security)。
## API
```js
import { useAudioPlayer, useAudioRecorder } from 'expo-audio';
```
## Constants
### `Audio.RecordingPresets`
Supported platforms: Android, iOS, tvOS, Web.
Type: { HIGH_QUALITY: [RecordingOptions](#recordingoptions), LOW_QUALITY: [RecordingOptions](#recordingoptions) }
Constant which contains definitions of the two preset examples of `RecordingOptions`, as implemented in the Audio SDK.
#### `HIGH_QUALITY`
```ts
RecordingPresets.HIGH_QUALITY = {
extension: '.m4a',
sampleRate: 44100,
numberOfChannels: 2,
bitRate: 128000,
android: {
outputFormat: 'mpeg4',
audioEncoder: 'aac',
},
ios: {
outputFormat: IOSOutputFormat.MPEG4AAC,
audioQuality: AudioQuality.MAX,
linearPCMBitDepth: 16,
linearPCMIsBigEndian: false,
linearPCMIsFloat: false,
},
web: {
mimeType: 'audio/webm',
bitsPerSecond: 128000,
},
};
```
#### `LOW_QUALITY`
```ts
RecordingPresets.LOW_QUALITY = {
extension: '.m4a',
sampleRate: 44100,
numberOfChannels: 2,
bitRate: 64000,
android: {
extension: '.3gp',
outputFormat: '3gp',
audioEncoder: 'amr_nb',
},
ios: {
audioQuality: AudioQuality.MIN,
outputFormat: IOSOutputFormat.MPEG4AAC,
linearPCMBitDepth: 16,
linearPCMIsBigEndian: false,
linearPCMIsFloat: false,
},
web: {
mimeType: 'audio/webm',
bitsPerSecond: 128000,
},
};
```
## Hooks
### `useAudioPlayer(source, options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source`(optional) | [AudioSource](#audiosource) | The audio source to load. Can be a local asset via `require()`, a remote URL, or null for no initial source. Default: `null` |
| `options`(optional) | [AudioPlayerOptions](#audioplayeroptions) | Audio player configuration options. Default: `{}` |
Creates an `AudioPlayer` instance that automatically releases when the component unmounts.
This hook manages the player's lifecycle and ensures it's properly disposed when no longer needed. The player will start loading the audio source immediately upon creation.
Returns: `AudioPlayer`
An `AudioPlayer` instance that's automatically managed by the component lifecycle.
Example
```tsx
import { useAudioPlayer } from 'expo-audio';
function MyComponent() {
const player = useAudioPlayer(require('./sound.mp3'));
return (
player.play()} />
);
}
```
Example
```tsx
import { useAudioPlayer } from 'expo-audio';
function MyComponent() {
const player = useAudioPlayer('https://example.com/audio.mp3', {
updateInterval: 1000,
downloadFirst: true,
});
return (
player.play()} />
);
}
```
### `useAudioPlayerStatus(player)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `player` | [AudioPlayer](#audioplayer) | The `AudioPlayer` instance to monitor. |
Hook that provides real-time playback status updates for an `AudioPlayer`.
This hook automatically subscribes to playback status changes and returns the current status. The status includes information about playback state, current time, duration, loading state, and more.
Returns: `AudioStatus`
The current `AudioStatus` object containing playback information.
Example
```tsx
import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio';
function PlayerComponent() {
const player = useAudioPlayer(require('./sound.mp3'));
const status = useAudioPlayerStatus(player);
return (
Playing: {status.playing ? 'Yes' : 'No'}Current Time: {status.currentTime}sDuration: {status.duration}s
);
}
```
### `useAudioPlaylist(options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `options`(optional) | [AudioPlaylistOptions](#audioplaylistoptions) | Audio playlist configuration options including initial sources and loop mode. Default: `{}` |
Creates an `AudioPlaylist` instance that automatically releases when the component unmounts.
This hook manages the playlist's lifecycle and ensures it's properly disposed when no longer needed. An audio playlist allows you to manage a collection of audio sources with gapless playback support.
Returns: `AudioPlaylist`
An `AudioPlaylist` instance that's automatically managed by the component lifecycle.
Example
```tsx
import { useAudioPlaylist } from 'expo-audio';
function PlaylistPlayer() {
const playlist = useAudioPlaylist({
sources: [
require('./track1.mp3'),
require('./track2.mp3'),
'https://example.com/track3.mp3',
],
loop: 'all',
});
return (
Track {playlist.currentIndex + 1} of {playlist.trackCount} playlist.previous()} />
playlist.playing ? playlist.pause() : playlist.play()} />
playlist.next()} />
);
}
```
### `useAudioPlaylistStatus(playlist)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `playlist` | [AudioPlaylist](#audioplaylist) | The `AudioPlaylist` instance to monitor. |
Hook that provides real-time status updates for an `AudioPlaylist`.
This hook automatically subscribes to playlist status changes and returns the current status. The status includes information about the current track, playback state, and playlist position.
Returns: `AudioPlaylistStatus`
The current `AudioPlaylistStatus` object containing playlist and playback information.
Example
```tsx
import { useAudioPlaylist, useAudioPlaylistStatus } from 'expo-audio';
function PlaylistStatusDisplay() {
const playlist = useAudioPlaylist({ sources: [require('./track1.mp3')] });
const status = useAudioPlaylistStatus(playlist);
return (
Track: {status.currentIndex + 1} / {status.trackCount}Time: {status.currentTime}s / {status.duration}sPlaying: {status.playing ? 'Yes' : 'No'}
);
}
```
### `useAudioRecorder(options, statusListener)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `options` | [RecordingOptions](#recordingoptions) | Recording configuration options including format, quality, sample rate, etc. |
| `statusListener`(optional) | (status: [RecordingStatus](#recordingstatus)) => void | Optional callback function that receives recording status updates. |
Hook that creates an `AudioRecorder` instance for recording audio.
This hook manages the recorder's lifecycle and ensures it's properly disposed when no longer needed. The recorder is automatically prepared with the provided options and can be used to record audio.
Returns: `AudioRecorder`
An `AudioRecorder` instance that's automatically managed by the component lifecycle.
Example
```tsx
import { useAudioRecorder, RecordingPresets } from 'expo-audio';
function RecorderComponent() {
const recorder = useAudioRecorder(
RecordingPresets.HIGH_QUALITY,
(status) => console.log('Recording status:', status)
);
const startRecording = async () => {
await recorder.prepareToRecordAsync();
recorder.record();
};
return (
);
}
```
### `useAudioRecorderState(recorder, interval)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `recorder` | [AudioRecorder](#audiorecorder) | The `AudioRecorder` instance to monitor. |
| `interval`(optional) | `number` | How often (in milliseconds) to poll the recorder's status. Defaults to 500ms. Default: `500` |
Hook that provides real-time recording state updates for an `AudioRecorder`.
This hook polls the recorder's status at regular intervals and returns the current recording state. Use this when you need to monitor the recording status without setting up a status listener.
Returns: `RecorderState`
The current `RecorderState` containing recording information.
Example
```tsx
import { useAudioRecorder, useAudioRecorderState, RecordingPresets } from 'expo-audio';
function RecorderStatusComponent() {
const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
const state = useAudioRecorderState(recorder);
return (
Recording: {state.isRecording ? 'Yes' : 'No'}Duration: {Math.round(state.durationMillis / 1000)}sCan Record: {state.canRecord ? 'Yes' : 'No'}
);
}
```
### `useAudioSampleListener(player, listener)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `player` | [AudioPlayer](#audioplayer) | The `AudioPlayer` instance to sample audio from. |
| `listener` | (data: [AudioSample](#audiosample)) => void | Function called with each audio sample containing waveform data. |
Hook that sets up audio sampling for an `AudioPlayer` and calls a listener with audio data.
This hook enables audio sampling on the player (if supported) and subscribes to audio sample updates. Audio sampling provides real-time access to audio waveform data for visualization or analysis.
> **Note:** Audio sampling requires `RECORD_AUDIO` permission on Android and is not supported on all platforms.
Returns: `void`
Example
```tsx
import { useEffect } from 'react';
import { useAudioPlayer, useAudioSampleListener, requestRecordingPermissionsAsync } from 'expo-audio';
function AudioVisualizerComponent() {
const player = useAudioPlayer(require('./music.mp3'));
// if required on Android, request recording permissions
useEffect(() => {
async function requestPermission() {
const { granted } = await requestRecordingPermissionsAsync();
if (granted) {
console.log("Permission granted");
}
}
requestPermission();
}, []);
useAudioSampleListener(player, (sample) => {
// Use sample.channels array for audio visualization
console.log('Audio sample:', sample.channels[0].frames);
});
return ;
}
```
## Classes
### `AudioPlayer`
Supported platforms: Android, iOS, tvOS, Web.
Type: Class extends [SharedObject](/versions/v55.0.0/sdk/expo#sharedobjecttype)<[AudioEvents](#audioevents)\>
AudioPlayer Properties
### `currentTime`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
The current position through the audio item in seconds.
### `duration`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
The total duration of the audio in seconds.
### `id`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string`
Unique identifier for the player object.
### `isAudioSamplingSupported`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether audio sampling is supported on the platform.
### `isBuffering`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is buffering.
### `isLoaded`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is finished loading.
### `loop`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is currently looping.
### `muted`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is currently muted.
### `paused`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is currently paused.
### `playbackRate`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
The current playback rate of the audio. It accepts different values depending on the platform:
- **Android**: `0.1` to `2.0`
- **iOS**: `0.0` to `2.0`
- **Web**: Follows browser implementation
Example
```tsx
import { useAudioPlayer } from 'expo-audio';
export default function App() {
const player = useAudioPlayer(source);
// Normal playback speed
player.playbackRate = 1.0;
// Slow motion (half speed)
player.playbackRate = 0.5;
// Fast playback (1.5x speed)
player.playbackRate = 1.5;
// Maximum speed on mobile
player.playbackRate = 2.0;
}
```
### `playing`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the player is currently playing.
### `shouldCorrectPitch`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
A boolean describing if we are correcting the pitch for a changed rate.
### `volume`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
The current volume of the audio.
**Range:** `0.0` to `1.0`. For example, `0.0` is completely silent (0%), `0.5` is half volume (50%), and `1.0` is full volume (100%).
Example
```tsx
import { useAudioPlayer } from 'expo-audio';
export default function App() {
const player = useAudioPlayer(source);
// Mute the audio
player.volume = 0.0;
// Set volume to 50%
player.volume = 0.5;
// Set to full volume
player.volume = 1.0;
}
```
AudioPlayer Methods
### `clearLockScreenControls()`
Supported platforms: Android, iOS, tvOS, Web.
Removes this player from lock screen controls if it's currently active. This will clear the lock screen's now playing info.
Returns: `void`
### `pause()`
Supported platforms: Android, iOS, tvOS, Web.
Pauses the player.
Returns: `void`
### `play()`
Supported platforms: Android, iOS, tvOS, Web.
Start playing audio.
Returns: `void`
### `remove()`
Supported platforms: Android, iOS, tvOS, Web.
Remove the player from memory to free up resources.
Returns: `void`
### `replace(source)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type |
| --- | --- |
| `source` | [AudioSource](#audiosource) |
Replaces the current audio source with a new one.
Returns: `void`
### `seekTo(seconds, toleranceMillisBefore, toleranceMillisAfter)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `seconds` | `number` | The number of seconds to seek by. |
| `toleranceMillisBefore`(optional) | `number` | The tolerance allowed before the requested seek time, in milliseconds. iOS only. |
| `toleranceMillisAfter`(optional) | `number` | The tolerance allowed after the requested seek time, in milliseconds. iOS only. |
Seeks the playback by the given number of seconds.
Returns: `Promise`
### `setActiveForLockScreen(active, metadata, options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `active` | `boolean` | Whether this player should be active for lock screen controls. |
| `metadata`(optional) | [AudioMetadata](#audiometadata) | Optional metadata to display on the lock screen (title, artist, album, artwork). |
| `options`(optional) | [AudioLockScreenOptions](#audiolockscreenoptions) | Optional configuration to configure the lock screen controls. |
Sets or removes this audio player as the active player for lock screen controls. Only one player can control the lock screen at a time.
> **Note:** For lock screen controls to work correctly, [`interruptionMode`](#interruptionmode) must be set to `doNotMix` using [`setAudioModeAsync`](#audiosetaudiomodeasyncmode). Without this, the OS might not associate lock screen controls with your player.
Returns: `void`
### `setPlaybackRate(rate, pitchCorrectionQuality)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `rate` | `number` | The playback rate of the audio. See [`playbackRate`](#playbackrate) property for detailed range information. |
| `pitchCorrectionQuality`(optional) | [PitchCorrectionQuality](#pitchcorrectionquality) | The quality of the pitch correction. |
Sets the current playback rate of the audio.
Returns: `void`
### `updateLockScreenMetadata(metadata)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `metadata` | [AudioMetadata](#audiometadata) | The metadata to display (title, artist, album, artwork). |
Updates the metadata displayed on the lock screen for this player. This method only has an effect if this player is currently active for lock screen controls.
Returns: `void`
### `AudioPlaylist`
Supported platforms: Android, iOS, tvOS, Web.
Type: Class extends [SharedObject](/versions/v55.0.0/sdk/expo#sharedobjecttype)<[AudioPlaylistEvents](#audioplaylistevents)\>
AudioPlaylist Properties
### `currentIndex`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Type: `number`
Index of the currently playing track in the playlist.
### `currentTime`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
Current playback position in seconds.
### `duration`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
Duration of the current track in seconds.
### `id`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string`
Unique identifier for the playlist instance.
### `isBuffering`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the playlist is buffering.
### `isLoaded`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the current track has finished loading.
### `loop`
Supported platforms: Android, iOS, tvOS, Web.
Type: [AudioPlaylistLoopMode](#audioplaylistloopmode)
Current loop mode.
### `muted`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the playlist is currently muted.
### `playbackRate`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
Current playback rate (1.0 = normal speed).
### `playing`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the playlist is currently playing.
### `sources`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Type: [AudioSourceInfo[]](#audiosourceinfo)
The audio sources currently in the playlist.
### `trackCount`
Supported platforms: Android, iOS, tvOS, Web.
Read Only • Type: `number`
Total number of tracks in the playlist.
### `volume`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
Current volume (0.0 to 1.0).
AudioPlaylist Methods
### `add(source)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source` | [AudioSource](#audiosource) | The audio source to add. |
Add a track to the end of the playlist.
Returns: `void`
### `clear()`
Supported platforms: Android, iOS, tvOS, Web.
Clear all tracks from the playlist.
Returns: `void`
### `destroy()`
Supported platforms: Android, iOS, tvOS, Web.
Destroy the playlist and free up resources.
Returns: `void`
### `insert(source, index)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source` | [AudioSource](#audiosource) | The audio source to insert. |
| `index` | `number` | The position to insert at. |
Insert a track at a specific position in the playlist.
Returns: `void`
### `next()`
Supported platforms: Android, iOS, tvOS, Web.
Skip to the next track in the playlist. If at the end of the playlist and loop mode is 'all', wraps to the first track. If loop mode is 'none' and at the end, does nothing.
Returns: `void`
### `pause()`
Supported platforms: Android, iOS, tvOS, Web.
Pause playback.
Returns: `void`
### `play()`
Supported platforms: Android, iOS, tvOS, Web.
Start playing the current track in the playlist.
Returns: `void`
### `previous()`
Supported platforms: Android, iOS, tvOS, Web.
Skip to the previous track in the playlist. If at the beginning of the playlist and loop mode is 'all', wraps to the last track. If loop mode is 'none' and at the beginning, does nothing.
Returns: `void`
### `remove(index)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `index` | `number` | The index of the track to remove. |
Remove a track from the playlist by index.
Returns: `void`
### `seekTo(seconds)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `seconds` | `number` | The position to seek to. |
Seeks the playback to a specific position in seconds.
Returns: `Promise`
### `skipTo(index)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `index` | `number` | The index of the track to skip to. |
Skip to a specific track in the playlist by index.
Returns: `void`
### `AudioRecorder`
Supported platforms: Android, iOS, tvOS, Web.
Type: Class extends [SharedObject](/versions/v55.0.0/sdk/expo#sharedobjecttype)<[RecordingEvents](#recordingevents)\>
AudioRecorder Properties
### `currentTime`
Supported platforms: Android, iOS, tvOS, Web.
Type: `number`
The current length of the recording, in seconds.
### `id`
Supported platforms: Android, iOS, tvOS, Web.
Type: `string`
Unique identifier for the recorder object.
### `isRecording`
Supported platforms: Android, iOS, tvOS, Web.
Type: `boolean`
Boolean value indicating whether the recording is in progress.
### `uri`
Supported platforms: Android, iOS, tvOS, Web.
Literal type: `union`
The uri of the recording.
Acceptable values are: `string` | `null`
AudioRecorder Methods
### `getAvailableInputs()`
Supported platforms: Android, iOS, tvOS, Web.
Returns a list of available recording inputs. This method can only be called if the `Recording` has been prepared.
Returns: `RecordingInput[]`
A `Promise` that is fulfilled with an array of `RecordingInput` objects.
### `getCurrentInput()`
Supported platforms: Android, iOS, tvOS, Web.
Returns the currently-selected recording input. This method can only be called if the `Recording` has been prepared.
Returns: `Promise`
A `Promise` that is fulfilled with a `RecordingInput` object.
### `getStatus()`
Supported platforms: Android, iOS, tvOS, Web.
Status of the current recording.
Returns: `RecorderState`
### `pause()`
Supported platforms: Android, iOS, tvOS, Web.
Pause the recording.
Returns: `void`
### `prepareToRecordAsync(options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type |
| --- | --- |
| `options`(optional) | [Partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype)<[RecordingOptions](#recordingoptions)\> |
Prepares the recording for recording.
Returns: `Promise`
### `record(options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `options`(optional) | [RecordingStartOptions](#recordingstartoptions) | Optional recording configuration options. |
Starts the recording.
Returns: `void`
> **Deprecated:** Use `record({ forDuration: seconds })` instead.
### `recordForDuration(seconds)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `seconds` | `number` | The time in seconds to stop recording at. |
Stops the recording once the specified time has elapsed.
Returns: `void`
### `setInput(inputUid)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `inputUid` | `string` | The uid of a `RecordingInput`. |
Sets the current recording input.
Returns: `void`
A `Promise` that is resolved if successful or rejected if not.
> **Deprecated:** Use `record({ atTime: seconds })` instead.
### `startRecordingAtTime(seconds)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `seconds` | `number` | The time in seconds to start recording at. |
Starts the recording at the given time.
Returns: `void`
### `stop()`
Supported platforms: Android, iOS, tvOS, Web.
Stop the recording.
Returns: `Promise`
## Methods
### `Audio.clearAllPreloadedSources()`
Supported platforms: Android, iOS, tvOS, Web.
Releases all preloaded audio sources to free memory.
Returns: `Promise`
### `Audio.clearPreloadedSource(source)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source` | [AudioSource](#audiosource) | The audio source to release. Must match the source previously passed to `preload()`. |
Releases a specific preloaded audio source to free memory.
Returns: `Promise`
### `Audio.createAudioPlayer(source, options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source`(optional) | [AudioSource](#audiosource) | The audio source to load. Default: `null` |
| `options`(optional) | [AudioPlayerOptions](#audioplayeroptions) | Audio player configuration options. Default: `{}` |
Creates an instance of an `AudioPlayer` that doesn't release automatically.
> For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-options) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.
Returns: `AudioPlayer`
### `Audio.createAudioPlaylist(options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `options`(optional) | [AudioPlaylistOptions](#audioplaylistoptions) | Audio playlist configuration options. Default: `{}` |
Creates an instance of an `AudioPlaylist` that doesn't release automatically.
> For most use cases you should use the [`useAudioPlaylist`](#useaudioplaylistoptions) hook instead.
Returns: `AudioPlaylist`
### `Audio.getPreloadedSources()`
Supported platforms: Android, iOS, tvOS, Web.
Returns the URIs of all currently preloaded audio sources.
On iOS, sources are removed from this list when consumed by `useAudioPlayer()`, `createAudioPlayer()`, or `player.replace()`. On Android and web, sources remain until explicitly cleared with `clearPreloadedSource()` / `clearAllPreloadedSources()`.
Returns: `Promise`
An array of URI strings for sources currently in the preload cache.
### `Audio.getRecordingPermissionsAsync()`
Supported platforms: Android, iOS, tvOS, Web.
Checks the current status of recording permissions without requesting them.
This function returns the current permission status for microphone access without triggering a permission request dialog. Use this to check permissions before deciding whether to call `requestRecordingPermissionsAsync()`.
Returns: `Promise`
A Promise that resolves to a `PermissionResponse` object containing the current permission status.
Example
```tsx
import { getRecordingPermissionsAsync, requestRecordingPermissionsAsync } from 'expo-audio';
const ensureRecordingPermissions = async () => {
const { status } = await getRecordingPermissionsAsync();
if (status !== 'granted') {
// Permission not granted, request it
const { granted } = await requestRecordingPermissionsAsync();
return granted;
}
return true; // Already granted
};
```
### `Audio.preload(source, options)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `source` | [AudioSource](#audiosource) | The audio source to preload. Can be a URL string, a local asset via `require()`, or an audio source object. |
| `options`(optional) | [PreloadOptions](#preloadoptions) | Optional configuration for preloading behavior. Default: `{}` |
Preloads an audio source for near-instant playback later.
This should be called in module scope, before any React components render. When the source is later used with `useAudioPlayer()`, `createAudioPlayer()`, or `player.replace()`, playback begins with minimal delay.
Returns: `Promise`
Example
```tsx
import { preload, useAudioPlayer } from 'expo-audio';
const track1 = 'https://example.com/track1.mp3';
const track2 = 'https://example.com/track2.mp3';
// Preload at module scope — starts buffering immediately
preload(track1);
preload(track2, { preferredForwardBufferDuration: 20 });
export default function App() {
const player = useAudioPlayer(track1);
// Playback starts near-instantly because the source was preloaded
return player.play()} />;
}
```
### `Audio.requestNotificationPermissionsAsync()`
Supported platforms: Android, iOS, tvOS, Web.
Requests permission to post notifications on Android.
This is required for showing media playback controls in the notification shade. This function is only available on Android and will throw on other platforms.
Returns: `Promise`
A Promise that resolves to a `PermissionResponse` object containing the permission status.
Example
```tsx
import { requestNotificationPermissionsAsync } from 'expo-audio';
const checkPermissions = async () => {
const { status, granted } = await requestNotificationPermissionsAsync();
if (granted) {
console.log('Notification permission granted');
} else {
console.log('Notification permission denied:', status);
}
};
```
### `Audio.requestRecordingPermissionsAsync()`
Supported platforms: Android, iOS, tvOS, Web.
Requests permission to record audio from the microphone.
This function prompts the user for microphone access permission, which is required for audio recording functionality. On iOS, this will show the system permission dialog. On Android, this requests the `RECORD_AUDIO` permission.
Returns: `Promise`
A Promise that resolves to a `PermissionResponse` object containing the permission status.
Example
```tsx
import { requestRecordingPermissionsAsync } from 'expo-audio';
const checkPermissions = async () => {
const { status, granted } = await requestRecordingPermissionsAsync();
if (granted) {
console.log('Recording permission granted');
} else {
console.log('Recording permission denied:', status);
}
};
```
### `Audio.setAudioModeAsync(mode)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `mode` | [Partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype)<[AudioMode](#audiomode)\> | Partial audio mode configuration object. Only specified properties will be updated. |
Configures the global audio behavior and session settings.
This function allows you to control how your app's audio interacts with other apps, background playback behavior, audio routing, and interruption handling.
Returns: `Promise`
A Promise that resolves when the audio mode has been applied.
Example
```tsx
import { setAudioModeAsync } from 'expo-audio';
// Configure audio for background playback with mixing
await setAudioModeAsync({
playsInSilentMode: true,
shouldPlayInBackground: true,
interruptionMode: 'mixWithOthers'
});
// Configure audio for recording
await setAudioModeAsync({
allowsRecording: true,
playsInSilentMode: true
});
```
### `Audio.setIsAudioActiveAsync(active)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `active` | `boolean` | Whether audio should be active (`true`) or disabled (`false`). |
Enables or disables the audio subsystem globally.
When set to `false`, this will pause all audio playback and prevent new audio from playing. This is useful for implementing app-wide audio controls or responding to system events.
Returns: `Promise`
A Promise that resolves when the audio state has been updated.
Example
```tsx
import { setIsAudioActiveAsync } from 'expo-audio';
// Disable all audio when app goes to background
const handleAppStateChange = async (nextAppState) => {
if (nextAppState === 'background') {
await setIsAudioActiveAsync(false);
} else if (nextAppState === 'active') {
await setIsAudioActiveAsync(true);
}
};
```
## Event Subscriptions
### `Audio.useAudioSampleListener(player, listener)`
Supported platforms: Android, iOS, tvOS, Web.
| Parameter | Type | Description |
| --- | --- | --- |
| `player` | [AudioPlayer](#audioplayer) | The `AudioPlayer` instance to sample audio from. |
| `listener` | (data: [AudioSample](#audiosample)) => void | Function called with each audio sample containing waveform data. |
Hook that sets up audio sampling for an `AudioPlayer` and calls a listener with audio data.
This hook enables audio sampling on the player (if supported) and subscribes to audio sample updates. Audio sampling provides real-time access to audio waveform data for visualization or analysis.
> **Note:** Audio sampling requires `RECORD_AUDIO` permission on Android and is not supported on all platforms.
Returns: `void`
Example
```tsx
import { useEffect } from 'react';
import { useAudioPlayer, useAudioSampleListener, requestRecordingPermissionsAsync } from 'expo-audio';
function AudioVisualizerComponent() {
const player = useAudioPlayer(require('./music.mp3'));
// if required on Android, request recording permissions
useEffect(() => {
async function requestPermission() {
const { granted } = await requestRecordingPermissionsAsync();
if (granted) {
console.log("Permission granted");
}
}
requestPermission();
}, []);
useAudioSampleListener(player, (sample) => {
// Use sample.channels array for audio visualization
console.log('Audio sample:', sample.channels[0].frames);
});
return ;
}
```
## Types
### `AndroidAudioEncoder`
Supported platforms: Android.
Literal Type: `string`
Audio encoder options for Android recording.
Specifies the audio codec used to encode recorded audio on Android. Different encoders offer different quality, compression, and compatibility trade-offs.
Acceptable values are: `'default'` | `'amr_nb'` | `'amr_wb'` | `'aac'` | `'he_aac'` | `'aac_eld'`
### `AndroidOutputFormat`
Supported platforms: Android.
Literal Type: `string`
Audio output format options for Android recording.
Specifies the container format for recorded audio files on Android. Different formats have different compatibility and compression characteristics.
Acceptable values are: `'default'` | `'3gp'` | `'mpeg4'` | `'amrnb'` | `'amrwb'` | `'aac_adts'` | `'mpeg2ts'` | `'webm'`
### `AudioEvents`
Supported platforms: Android, iOS, tvOS, Web.
Event types that an `AudioPlayer` can emit.
These events allow you to listen for changes in playback state and receive real-time audio data. Use `player.addListener()` to subscribe to these events.
| Property | Type | Description |
| --- | --- | --- |
| audioSampleUpdate | (data: [AudioSample](#audiosample)) => void | Fired when audio sampling is enabled and new sample data is available. |
| playbackStatusUpdate | (status: [AudioStatus](#audiostatus)) => void | Fired when the player's status changes (play/pause/seek/load and so on.). |
> **Deprecated:** Use `AudioPlayerOptions` instead. Options for audio loading behavior.
### `AudioLoadOptions`
Supported platforms: Android, iOS, tvOS, Web.
Type: [AudioPlayerOptions](#audioplayeroptions)
### `AudioLockScreenOptions`
Supported platforms: Android, iOS, tvOS, Web.
Options for configuring which playback controls should be displayed on the lock screen.
| Property | Type | Description |
| --- | --- | --- |
| isLiveStream(optional) | `boolean` | Whether the audio is a live stream. When `true`, the lock screen will hide the duration and scrub bar, and disable seek controls. |
| showSeekBackward(optional) | `boolean` | Whether the seek backward button should be displayed on the lock screen. |
| showSeekForward(optional) | `boolean` | Whether the seek forward button should be displayed on the lock screen. |
### `AudioMetadata`
Supported platforms: Android, iOS, tvOS, Web.
| Property | Type | Description |
| --- | --- | --- |
| albumTitle(optional) | `string` | - |
| artist(optional) | `string` | - |
| artworkUrl(optional) | `string` | - |
| title(optional) | `string` | - |
### `AudioMode`
Supported platforms: Android, iOS, tvOS, Web.
| Property | Type | Description |
| --- | --- | --- |
| allowsBackgroundRecording(optional) | `boolean` | Supported platforms: Android, iOS. Whether audio recording should continue when the app moves to the background. Default: `false` |
| allowsRecording(optional) | `boolean` | Supported platforms: iOS. Whether the audio session allows recording. Default: `false` |
| interruptionMode(optional) | [InterruptionMode](#interruptionmode) | Determines how the audio session interacts with other audio sessions.
- `'doNotMix'`: Requests exclusive audio focus. Other apps will pause their audio.
- `'duckOthers'`: Requests audio focus with ducking. Other apps lower their volume but continue playing.
- `'mixWithOthers'`: Audio plays alongside other apps without interrupting them. On Android, this means no audio focus is requested. Best suited for sound effects, UI feedback, or short audio clips.
. Default: `'mixWithOthers'` |
| interruptionModeAndroid(optional) | [InterruptionModeAndroid](#interruptionmodeandroid) | Deprecated: Use interruptionMode instead, which now works on both platforms. . Supported platforms: Android. Determines how the audio session interacts with other sessions on Android. |
| playsInSilentMode(optional) | `boolean` | Determines if audio playback is allowed when the device is in silent mode. On Android, when `false`, playback is suppressed when the ringer mode is silent or vibrate. Default: `true` |
| shouldPlayInBackground(optional) | `boolean` | Whether the audio session stays active when the app moves to the background. Note: On Android, you have to enable the lockscreen controls with setActiveForLockScreen for sustained background playback. Otherwise, the audio will stop after approximately 3 minutes of background playback (OS limitation). Make sure to also appropriately configure the config-plugin. Default: `false` |
| shouldRouteThroughEarpiece(optional) | `boolean` | Whether the audio should route through the earpiece. On iOS, this only has an effect when `allowsRecording` is `true` (i.e., the audio session category is `.playAndRecord`). When `false` (the default), audio is routed through the speaker. Default: `false` |
### `AudioPlayerOptions`
Supported platforms: Android, iOS, tvOS, Web.
Options for configuring audio player behavior.
| Property | Type | Description |
| --- | --- | --- |
| crossOrigin(optional) | `'anonymous' | 'use-credentials'` | Supported platforms: Web. Determines the [cross origin policy](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/crossorigin) used by the underlying native view on web. If `undefined` (default), does not use CORS at all. If set to `'anonymous'`, the audio will be loaded with CORS enabled. Note that some audio may not play if CORS is enabled, depending on the CDN settings. If you encounter issues, consider adjusting the `crossOrigin` property. Default: `undefined` |
| downloadFirst(optional) | `boolean` | Supported platforms: Android, iOS, Web. If set to `true`, the system will attempt to download the resource to the device before loading. This value defaults to `false`. Works with:
- Local assets from `require('path/to/file')`
- Remote HTTP/HTTPS URLs
- Asset objects
. When enabled, this ensures the audio file is fully downloaded before playback begins. This can improve playback performance and reduce buffering, especially for users managing multiple audio players simultaneously. On Android and iOS, this will download the audio file to the device's tmp directory before playback begins. The system will purge the file at its discretion. On web, this will download the audio file to the user's device memory and make it available for the user to play. The system will usually purge the file from memory after a reload or on memory pressure. On web, CORS restrictions apply to the blob url, so you need to make sure the server returns the `Access-Control-Allow-Origin` header. |
| keepAudioSessionActive(optional) | `boolean` | Supported platforms: iOS. If set to `true`, the audio session will not be deactivated when this player pauses or finishes playback. This prevents interrupting other audio sources (like videos) when the audio ends. Useful for sound effects that should not interfere with ongoing video playback or other audio. The audio session for this player will not be deactivated automatically when the player finishes playback. Note: If needed, you can manually deactivate the audio session using setIsAudioActiveAsync(false). Default: `false` |
| preferredForwardBufferDuration(optional) | `number` | Supported platforms: Android, iOS. The duration in seconds the player should buffer ahead of the current playback position. A higher value improves playback stability at the cost of more memory/network usage.
- **iOS**: Maps to `AVPlayerItem.preferredForwardBufferDuration`. A value of `0` lets the system decide.
- **Android**: Configures ExoPlayer's `DefaultLoadControl` max buffer duration.
- **Web**: Not applicable (browser manages buffering).
. Default: `0 (system default)` |
| updateInterval(optional) | `number` | Supported platforms: Android, iOS, Web. How often (in milliseconds) to emit playback status updates. Defaults to 500ms. Default: `500ms`. Example
```tsx
import { useAudioPlayer } from 'expo-audio';
export default function App() {
const player = useAudioPlayer(source);
// High-frequency updates for smooth progress bars
const player = useAudioPlayer(source, { updateInterval: 100 });
// Standard updates (default behavior)
const player = useAudioPlayer(source, { updateInterval: 500 });
// Low-frequency updates for better performance
const player = useAudioPlayer(source, { updateInterval: 1000 });
}
```
|
### `AudioPlaylistEvents`
Supported platforms: Android, iOS, tvOS, Web.
Event types that an `AudioPlaylist` can emit.
These events allow you to listen for changes in playlist playback state. Use `playlist.addListener()` to subscribe to these events.
| Property | Type | Description |
| --- | --- | --- |
| playlistStatusUpdate | (status: [AudioPlaylistStatus](#audioplayliststatus)) => void | Fired when the playlist's status changes (play/pause/seek/load/track change). |
| trackChanged | `(data: { currentIndex: number, previousIndex: number }) => void` | Fired when the current track changes (next/previous/skip). |
### `AudioPlaylistLoopMode`
Supported platforms: Android, iOS, tvOS, Web.
Literal Type: `string`
Loop mode for audio playlist playback.
- `'none'`: No looping. Playback stops after the last track.
- `'single'`: Loops the current track indefinitely.
- `'all'`: Loops the entire playlist, returning to the first track after the last.
Acceptable values are: `'none'` | `'single'` | `'all'`
### `AudioPlaylistOptions`
Supported platforms: Android, iOS, tvOS, Web.
Options for configuring an audio playlist.
| Property | Type | Description |
| --- | --- | --- |
| crossOrigin(optional) | `'anonymous' | 'use-credentials'` | Supported platforms: Web. Sets the `crossOrigin` attribute on the `