# Expo SDK v52.0.0 Documentation Documentation for Expo SDK v52.0.0 libraries, app configuration files, Expo CLI, create-expo-app, and more. # app.json / app.config.js A reference of available properties in Expo app config. The following is a list of properties that are available for you under the `"expo"` key in app.json or app.config.json. These properties can be passed to the top level object of app.config.js or app.config.ts. Configuration with app config For information on app configuration, the differences between various app config files, and how to use them dynamically. ## Properties `name` Type: `string` The name of your app as it appears both within Expo Go and on your home screen as a standalone app. Bare Workflow 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. On iOS this corresponds to `CFBundleShortVersionString`, and on Android, this corresponds to `versionName`. The required format can be found [here. Bare Workflow 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"]`. 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` Locks your app to a specific orientation with portrait or landscape. Defaults to no lock. Valid values: `default`, `portrait`, `landscape` `userInterfaceStyle` Type: `enum` 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. Bare Workflow 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, [Android 7.1 and below, and [Android 8+) and to provide your new icon in each existing size. `notification` Type: `object` Configuration for remote (push) notifications. `icon` Type: `string` Path: `notification.icon` (Android only) Local path or remote URL to an image to use as the icon for push notifications. 96x96 png grayscale with transparency. We recommend following [Google's design guidelines. If not provided, defaults to your app icon. `color` Type: `string` Path: `notification.color` (Android only) Tint color for the push notification image when it appears in the notification tray. Defaults to `#ffffff` 6 character long hex color string, for example, `'#000000'` `iosDisplayInForeground` Type: `boolean` Path: `notification.iosDisplayInForeground` Whether or not to display notifications when the app is in the foreground on iOS. `_displayInForeground` option in the individual push notification message overrides this option. [Learn more. Defaults to `false`. `androidMode` Type: `enum` Path: `notification.androidMode` Show each push notification individually (`default`) or collapse into one (`collapse`). `androidCollapsedTitle` Type: `string` Path: `notification.androidCollapsedTitle` If `androidMode` is set to `collapse`, this title is used for the collapsed notification message. For example, `'#{unread_notifications} new interactions'`. `androidStatusBar` Type: `object` Configuration for the status bar on Android. For more details please navigate to [Configuring StatusBar. `barStyle` Type: `enum` 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. `androidNavigationBar` Type: `object` Configuration for the bottom navigation bar on Android. Can be used to configure the `expo-navigation-bar` module in EAS Build. `visible` Type: `enum` Path: `androidNavigationBar.visible` Determines how and when the navigation bar is shown. [Learn more. Requires `expo-navigation-bar` be installed in your project. Valid values: `leanback`, `immersive`, `sticky-immersive` `leanback` results in the navigation bar being hidden until the first touch gesture is registered. `immersive` results in the navigation bar being hidden until the user swipes up from the edge where the navigation bar is hidden. `sticky-immersive` is identical to `'immersive'` except that the navigation bar will be semi-transparent and will be hidden again after a short period of time. `barStyle` Type: `enum` Path: `androidNavigationBar.barStyle` Configure the navigation bar icons to have a light or dark color. Supported on Android Oreo and newer. Valid values: `'light-content'`, `'dark-content'` `backgroundColor` Type: `string` Path: `androidNavigationBar.backgroundColor` Specifies the background color of the navigation bar. 6 character long hex color string, for example, `'#000000'` `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 "-" Bare Workflow 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) `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` 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` 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. `locales` Type: `object` Provide overrides by locale for System Dialog prompts like Permissions Boxes Bare Workflow 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. Bare Workflow Plugins that add modifications can only be used with [prebuilding and managed EAS Build `splash` Type: `object` Configuration for loading and splash screen for standalone apps. Bare Workflow 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-` (Android Studio can [generate the appropriate image files for you). Be sure to follow the guidelines for each platform ([iOS, [Android 7.1 and below, and [Android 8+) and to provide your new icon in each required size. `backgroundColor` Type: `string` Path: `splash.backgroundColor` Color to fill the loading screen background 6 character long hex color string, for example, `'#000000'` Bare Workflow For Android, edit the `colorPrimary` item in `android/app/src/main/res/values/colors.xml` `resizeMode` Type: `enum` Path: `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: `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. `jsEngine` Type: `enum` @deprecated This field will be removed in a future release. When it is removed, you can continue using JavaScriptCore instead of Hermes by following the instructions in [@react-native-community/javascriptcore. Specifies the JavaScript engine for Android apps. Defaults to `hermes`. Valid values: `hermes`, `jsc`. Bare Workflow To change the JavaScript engine, update the `expo.jsEngine` value in `ios/Podfile.properties.json` or `android/gradle.properties` `newArchEnabled` Type: `boolean` A Boolean value that indicates whether the app should use the new architecture. Defaults to true. `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. `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. Bare Workflow 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. (Note: Transporter will pull the value for `Version Number` from `expo.version` and NOT from `expo.ios.buildNumber`.) Bare Workflow 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 "-" Bare Workflow To change your app's scheme, replace all occurrences of the old scheme in `Info.plist` and `AndroidManifest.xml` `icon` One of types: * `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 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 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. 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 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 key for your standalone app. `googleMobileAdsAppId` Type: `string` Path: `ios.config.googleMobileAdsAppId` [Google Mobile Ads App ID Google AdMob App ID. `googleMobileAdsAutoInit` Type: `boolean` Path: `ios.config.googleMobileAdsAutoInit` 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`. `googleServicesFile` Type: `string` Path: `ios.googleServicesFile` [Firebase Configuration File 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`. Bare Workflow 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. Bare Workflow 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` Bare Workflow Use Xcode to set `UIRequiresFullScreen` `userInterfaceStyle` Type: `enum` 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 `NSPrivacyAccessedAPITypes` Type: `array` Path: `ios.privacyManifests.NSPrivacyAccessedAPITypes` A list of required reasons of why your app uses restricted API categories. [Learn more `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. Entries must follow the format `applinks:[:port number]`. [Learn more. Bare Workflow Build with EAS, or use Xcode to enable this capability manually. [Learn more. `usesIcloudStorage` Type: `boolean` Path: `ios.usesIcloudStorage` A boolean indicating if the app uses iCloud Storage for `DocumentPicker`. See `DocumentPicker` docs for details. Bare Workflow 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 before you can submit your app for review with this capability. `splash` Type: `object` Path: `ios.splash` 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` 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` 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. `jsEngine` Type: `enum` Path: `ios.jsEngine` @deprecated This field will be removed in a future release. When it is removed, you can continue using JavaScriptCore instead of Hermes by following the instructions in [@react-native-community/javascriptcore. Specifies the JavaScript engine for iOS apps. Not supported in Expo Go. Defaults to `hermes`. Valid values: `hermes`, `jsc`. Bare Workflow To change the JavaScript engine, update the `expo.jsEngine` value in `ios/Podfile.properties.json` `newArchEnabled` Type: `boolean` Path: `ios.newArchEnabled` A Boolean value that indicates whether the iOS app should use the new architecture. `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. This corresponds to `CFBundleShortVersionString`. The required format can be found [here. Bare Workflow 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. Bare Workflow 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 Bare Workflow 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'` Bare Workflow This is set in `android/app/src/main/AndroidManifest.xml` under `android:windowBackground` `userInterfaceStyle` Type: `enum` 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 "-" Bare Workflow 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 `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. 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. 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. `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']` Bare Workflow 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 Location of the `google-services.json` file for configuring Firebase. Including this key automatically enables FCM in your standalone app. Bare Workflow 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 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 configuration for your standalone app. `apiKey` Type: `string` Path: `android.config.googleMaps.apiKey` Your Google Maps Android SDK API key `googleMobileAdsAppId` Type: `string` Path: `android.config.googleMobileAdsAppId` [Google Mobile Ads App ID Google AdMob App ID. `googleMobileAdsAutoInit` Type: `boolean` Path: `android.config.googleMobileAdsAutoInit` 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` `splash` Type: `object` Path: `android.splash` 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` 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 `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 `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 `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 `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 `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` 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 `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 `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 `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 `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 `Scale 4x` `intentFilters` Type: `array` Path: `android.intentFilters` Configuration for setting an array of custom intent filters in Android manifest. [Learn more Bare Workflow This is set in `AndroidManifest.xml` directly. [Learn more. 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 `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` 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`. `jsEngine` Type: `enum` Path: `android.jsEngine` @deprecated This field will be removed in a future release. When it is removed, you can continue using JavaScriptCore instead of Hermes by following the instructions in [@react-native-community/javascriptcore. Specifies the JavaScript engine for Android apps. Defaults to `hermes`. Valid values: `hermes`, `jsc`. Bare Workflow To change the JavaScript engine, update the `expo.jsEngine` value in `android/gradle.properties` `newArchEnabled` Type: `boolean` Path: `android.newArchEnabled` A Boolean value that indicates whether the Android app should use the new architecture. `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. This corresponds to `versionName`. The required format can be found [here. Bare Workflow To change your app version, edit the `versionName` string in `android/app/build.gradle` `edgeToEdgeEnabled` Type: `boolean` Path: `android.edgeToEdgeEnabled` Enable your app to run in [edge-to-edge mode. Default to false. Bare Workflow To change the setting, update the `expo.edgeToEdgeEnabled` value in `android/gradle.properties` and update the `AppTheme`'s `parent` attribute to one of the [Theme.EdgeToEdge values in `styles.xml` `web` Type: `object` Configuration that is specific to the web platform. `output` Type: `enum` 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` 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` 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` 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` 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. Bare Workflow Use [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` 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 `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` 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. `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). `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 `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. `remoteBuildCache` Type: `object` Path: `experiments.remoteBuildCache` Experimentally enable downloading cached builds from remote. `provider` Type: `undefined` Path: `experiments.remoteBuildCache.provider` Service provider for remote builds. `_internal` Type: `object` Internal properties for developer tools `pluginHistory` Type: `object` Path: `_internal.pluginHistory` List of plugins already run on the config --- # metro.config.js [ A reference of available configurations in Metro. See more information about metro.config.js in the [customizing Metro guide. ## Environment variables Expo CLI can load environment variables from .env files. Learn more about how to use environment variables in Expo CLI in the [environment variables guide. EAS CLI uses a different mechanism for environment variables, except when it invokes Expo CLI for compiling and bundling. Learn more about [environment variables in EAS. If you are migrating an older project, then you should ignore local env files by adding the following to your .gitignore: .gitignore ``` # local env files .env*.local ``` ### Disabling dotenv files Dotenv file loading can be fully disabled in Expo CLI by enabling the `EXPO_NO_DOTENV` environment variable, before invoking any Expo CLI command. `# All users can run cross-env, followed by the Expo CLI command` `npx cross-env EXPO_NO_DOTENV=1 expo start` `# Alternatively, macOS and Linux users can define the environment variable, then run npx, followed by the Expo CLI command` `-` `EXPO_NO_DOTENV=1 npx expo start` ### Disabling `EXPO_PUBLIC_`\-prefixed client environment variables Environment variables prefixed with `EXPO_PUBLIC_` will be exposed to the app at build-time. For example, `EXPO_PUBLIC_API_KEY` will be available as `process.env.EXPO_PUBLIC_API_KEY`. Client environment variable inlining can be disabled with the environment variable `EXPO_NO_CLIENT_ENV_VARS=1`, this must be defined before any bundling is performed. `# All users can run cross-env, followed by the Expo CLI command` `npx cross-env EXPO_NO_CLIENT_ENV_VARS=1 expo start` `# Alternatively, macOS and Linux users can define the environment variable, then run npx, followed by the Expo CLI command` `-` `EXPO_NO_CLIENT_ENV_VARS=1 npx expo start` ## CSS > CSS support is under development and currently only works on web. Expo supports CSS in your project. You can import CSS files from any component. CSS Modules are also supported. CSS support is enabled by default. You can disable the feature by setting `isCSSEnabled` in the Metro config. metro.config.js ``` /** @type {import('expo/metro-config').MetroConfig} */ const config = getDefaultConfig(__dirname, { // Disable CSS support. isCSSEnabled: false, }); ``` To enable CSS support, set `isCSSEnabled` to `true` in the Metro config. metro.config.js ``` /** @type {import('expo/metro-config').MetroConfig} */ const config = getDefaultConfig(__dirname, { isCSSEnabled: true, }); ``` ### Global CSS > Global styles are web-only, usage will cause your application to diverge visually on native. You can import a CSS file from any component. The CSS will be applied to the entire page. Here, we'll define a global style for the class name `.container`: styles.css ``` .container { background-color: red; } ``` We can then use the class name in our component by importing the stylesheet and using `.container`: App.js ``` import './styles.css'; import { View } from 'react-native'; export default function App() { return ( ``` <> {/* Use `className` to assign the style with React DOM components. */}
Hello World
``` {/* Use `style` with the following syntax to append class names in React Native for web. */} Hello World ``` ); } ``` You can also import stylesheets that are vendored in libraries, just like you would any node module: index.js ``` // Applies the styles app-wide. import 'emoji-mart/css/emoji-mart.css'; ``` * On native, all global stylesheets are automatically ignored. * Hot reloading is supported for global stylesheets, simply save the file and the changes will be applied. ### CSS Modules > CSS Modules for native are under development and currently only work on web. CSS Modules are a way to scope CSS to a specific component. This is useful for avoiding naming collisions and for ensuring that styles are only applied to the intended component. In Expo, CSS Modules are defined by creating a file with the `.module.css` extension. The file can be imported from any component. The exported value is an object with the class names as keys and the web-only scoped names as the values. The import `unstable_styles` can be used to access `react-native-web`\-safe styles. CSS Modules support platform extensions to allow you to define different styles for different platforms. For example, you can define a `module.ios.css` and `module.android.css` file to define styles for Android and iOS respectively. You'll need to import without the extension, for example: App.js ``` // Importing `./App.module.ios.css`: - import styles from './App.module.css'; + import styles from './App.module'; ``` Flipping the extension, for example, `App.ios.module.css` will not work and result in a universal module named `App.ios.module`. > You cannot pass styles to the `className` prop of a React Native or React Native for web component. Instead, you must use the `style` prop. App.js ``` import styles, { unstable_styles } from './App.module.css'; export default function Page() { return ( ``` <> Hello World Hello World {/* Web-only usage: */}

Hello World

``` ); } ``` App.module.css ``` .text { color: red; } ``` * On web, all CSS values are available. CSS is not processed or auto-prefixed like it is with the React Native Web `StyleSheet` API. You can use `postcss.config.js` to autoprefix your CSS. * CSS Modules use [lightningcss under the hood, check [the issues for unsupported features. ### PostCSS > Changing the Post CSS or `browserslist` config will require you to clear the Metro cache: `npx expo start --clear` | `npx expo export --clear`. [PostCSS can be customized by adding a `postcss.config.json` file to the root of your project. This file should export a function that returns a PostCSS configuration object. For example: postcss.config.json ``` { "plugins": { ``` "autoprefixer": {} ``` } } ``` Both `postcss.config.json` and `postcss.config.js` are supported, but `postcss.config.json` enables better caching. ### SASS Expo Metro has _partial_ support for SCSS/SASS. To setup, install the `sass` package in your project: `-` `yarn add -D sass` Then, ensure [CSS is setup in the metro.config.js file. * When `sass` is installed, then modules without extensions will be resolved in the following order: `scss`, `sass`, `css`. * Only use the intended syntax with `sass` files. * Importing other files from inside a scss/sass file is not currently supported. ### Tailwind > Standard Tailwind CSS supports only web platform. For universal support, use a library such as [NativeWind, which allows creating styled React Native components with Tailwind CSS. Tailwind CSS Learn how to configure and use Tailwind CSS in your Expo project. ## Extending the Babel transformer Expo's Metro config uses a custom `transformer.babelTransformerPath` value to ensure `expo-babel-preset` is always used and web/Node.js environments are supported. If you want to extend the Babel transformer, import the upstream transformer from `@expo/metro-config/babel-transformer` instead of `metro-react-native-babel-transformer`. For example: metro.transformer.js ``` const upstreamTransformer = require('@expo/metro-config/babel-transformer'); module.exports.transform = async ({ src, filename, options }) => { // Do something custom for SVG files... if (filename.endsWith('.svg')) { ``` src = '...'; ``` } // Pass the source through the upstream Expo transformer. return upstreamTransformer.transform({ src, filename, options }); }; ``` ## Custom resolving Expo CLI extends the default Metro resolver to add features like Web, Server, and tsconfig aliases support. You can similarly customize the default resolution behavior of Metro by chaining the `config.resolver.resolveRequest` function. metro.config.js ``` 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:')) { ``` // Logic to resolve the module name to a file path... // NOTE: Throw an error if there is no resolution. return { filePath: 'path/to/file', type: 'sourceFile', }; ``` } // Ensure you call the default resolver. return context.resolveRequest(context, moduleName, platform); }; module.exports = config; ``` Unlike traditional bundlers, Metro shared the same resolver function across all platforms. As a result, you can mutate the resolution settings dynamically on each request with the `context` object. ### Mocking modules If you want a module to be empty for a given platform, you can return a `type: 'empty'` object from the resolver. The following example will cause `lodash` to be empty on web: metro.config.js ``` 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', }; ``` } // Ensure you call the default resolver. return context.resolveRequest(context, moduleName, platform); }; module.exports = config; ``` This technique is equivalent to using empty externals in Webpack or Vite, but with the added benefit of being able to target specific platforms. ### Virtual modules Metro doesn't support virtual modules at the moment. One technique you can use to obtain similar behavior is to create a module in the `node_modules/.cache/...` directory and redirect the resolution to that file. The following example will create a module at `node_modules/.cache/virtual/virtual-module.js` and redirect the resolution of `virtual:my-module` to that file: metro.config.js ``` 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'); // Create the virtual module in a generated directory... 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', }; ``` } // Ensure you call the default resolver. return context.resolveRequest(context, moduleName, platform); }; module.exports = config; ``` This can be used to emulate `externals` with custom imports. For example, if you want to redirect `require('expo')` to something custom like `SystemJS.require('expo')`, you can create a virtual module that exports `SystemJS.require('expo')` and redirect the resolution of `expo` to that file. ## Custom transforming > Transformations are heavily cached in Metro. If you update something, use the `--clear` flag to see updates. For example, `npx expo start --clear`. Metro doesn't have a very expressive plugin system for transforming files, instead opt to use the [babel.config.js and caller object to customize the transformation. babel.config.js ``` module.exports = function (api) { // Get the platform that Expo CLI is transforming for. const platform = api.caller(caller => (caller ? caller.platform : 'ios')); // Detect if the bundling operation is for Hermes engine or not, e.g. `'hermes'` | `undefined`. const engine = api.caller(caller => (caller ? caller.engine : null)); // Is bundling for a server environment, e.g. API Routes. const isServer = api.caller(caller => (caller ? caller.isServer : false)); // Is bundling for development or production. const isDev = api.caller(caller => ``` caller ? caller.isDev : process.env.BABEL_ENV === 'development' || process.env.NODE_ENV === 'development' ``` ); // Ensure the config is not cached otherwise the platform will not be updated. api.cache(false); // You can alternatively provide a more robust CONFIG cache invalidation: // api.cache.invalidate(() => platform); return { ``` presets: ['babel-preset-expo'], plugins: [ // Add a plugin based on the platform... platform === 'web' && 'my-plugin', ``` // Ensure you filter out falsy values. ].filter(Boolean), ``` }; }; ``` If the caller doesn't have `engine`, `platform`, `bundler`, and so on, then ensure you are using `@expo/metro-config/babel-transformer` for the transformer. If you're using a custom transformer then it may need to extend the Expo transformer. Always try to implement custom logic in the resolver if possible, caching is much simpler and easier to reason about. For example, if you need to remap an import, it's simpler and faster to resolve to a static file with the resolver than to parse all possible import methods and remap them with the transformer. Always use `babel-preset-expo` as the default Babel preset, this ensures the transformation is always compatible with Expo runtimes. `babel-preset-expo` uses all of the caller inputs internally to optimize for a given platform, engine, and environment. ## Node.js built-ins When bundling for a server environment, Expo's Metro config automatically supports externalizing Node.js built-in modules (`fs`, `path`, `node:crypto`, and more) based on the current Node.js version. If the CLI is bundling for a browser environment, then built-ins will first check if the module is installed locally, then fallback on an empty shim. For example, if you install `path` for use in the browser, this can be used, otherwise, the module will automatically be skipped. ## Environment settings Expo's Metro config injects build settings that can be used in the client bundle via environment variables. All variables will be inlined and cannot be used dynamically. For example, `process.env["EXPO_BASE_URL"]` won't work. * `process.env.EXPO_BASE_URL` exposes the base URL defined in `experiments.baseUrl`. This is used in Expo Router to respect the production base URL for deployment. > These environment variables will not be defined in test environments! ## Bundle splitting > This feature is web-only in SDK 50. In SDK 50, Expo CLI automatically splits web bundles into multiple chunks based on async imports in production. This feature requires `@expo/metro-runtime` to be installed and imported somewhere in the entry bundle (available by default in Expo Router). Shared dependencies of async bundles are merged into a single chunk to reduce the number of requests. For example, if you have two async bundles that import `lodash`, then the library is merged into a single initial chunk. As of SDK 50, the chunk splitting heuristic cannot be customized. For example: `math.js` `index.js` math.js ``` export function add(a, b) { return a + b; } ``` index.js ``` import '@expo/metro-runtime'; // This will be split into a separate chunk. import('./math').then(math => { console.log(math.add(1, 2)); }); ``` When you run `npx expo export -p web`, the bundles are split into multiple files, and the entry bundle is added to the main HTML file. `@expo/metro-runtime` adds the runtime code that loads and evaluates the async bundles. ## Source map debug ID > Available from SDK 50 on all platforms. If a bundle is exported with an external source map, a [Debug ID annotation will be added to the end of the file, along with a matching `debugId` in the source map for corresponding the files together. If no source maps are exported, or inline source maps are used then this annotation will not be added. ``` // //# debugId= ``` The associated `*.js.map` or `*.hbc.map` source map will be a JSON file containing an equivalent `debugId` property. The `debugId` will be injected before hermes bytecode generation to ensure matching in all cases. The `debugId` is a deterministic hash of the bundle's contents without the external bundle splitting references. This is the same value used to create a chunks filename but formatted as a UUID. For example, `431b98e2-c997-4975-a3d9-2987710abd44`. `@expo/metro-config` injects `debugId` during `npx expo export` and `npx expo export:embed`. Any additional optimization steps in `npx expo export:embed` like Hermes bytecode generation will need to have the `debugId` injected manually. ## Metro require runtime You can optionally enable a custom Metro `require` implementation with the environment variable `EXPO_USE_METRO_REQUIRE=1`. This runtime has the following features: * String module IDs that are human-readable and make missing module errors easier to follow. * Deterministic IDs that are the same between runs and across modules (required for React Server Components in development). * Removed support for legacy RAM bundles. ## Magic import comments > Available from SDK 52 on all platforms. Server environments such as Workers, and Node.js support import arbitrary files at runtime, so you may want to keep `import` syntax in-tact instead of using Metro's require system. You can opt-out dynamic imports with the `/* @metro-ignore */` comment in `import()` statements. ``` // Manually ensure `./my-module.js` is included in the correct spot relative to the module. const myModule = await import(/* @metro-ignore */ './my-module.js'); ``` Expo CLI will skip the `./my-module.js` dependency and assume that the developer has manually added it to the output bundle. Internally, this is used for exporting custom server code that dynamically switches between files based on the request. Avoid using this syntax for native bundles since `import()` is generally not available in React Native with Hermes enabled. ## Asset imports When assets are imported, a virtual module is created to represent the data required for importing the asset. On native platforms, an asset will be a numeric ID: `1`, `2`, `3`, and so on, which can be looked up using `require("@react-native/assets-registry/registry").getAssetByID()`. On web and server platforms, the asset will change depending on the file type. If the file is an image, then the asset will be `{ uri: string, width?: number, height?: number }`, otherwise the asset will be a `string` representing the remote URL for the asset. The assets can be used as follows: ``` import { Image } from 'react-native'; import asset from './img.png'; function Demo() { return ; } ``` In API routes, you can always assume the type of the asset will not be a number: ``` import asset from './img.png'; export async function GET(req: Request) { const ImageData = await fetch( ``` new URL( // Access the asset URI. asset.uri, // Append to the current request URL origin. req.url ) ``` ).then(res => res.arrayBuffer()); return new Response(ImageData, { ``` headers: { 'Content-Type': 'image/png', }, ``` }); } ``` ## Bare workflow setup > This guide is versioned and will need to be revisited when upgrading/downgrading Expo. Alternatively, use [Expo Prebuild for fully automated setup. Projects that don't use [Expo Prebuild must configure native files to ensure the Expo Metro config is always used to bundle the project. These modifications are meant to replace `npx react-native bundle` and `npx react-native start` with `npx expo export:embed` and `npx expo start` respectively. ### metro.config.js Ensure the metro.config.js extends `expo/metro-config`: ``` const { getDefaultConfig } = require('expo/metro-config'); const config = getDefaultConfig(__dirname); module.exports = config; ``` ### `android/app/build.gradle` The Android `app/build.gradle` must be configured to use Expo CLI for production bundling. Modify the `react` config object: ``` react { ... + // Use Expo CLI to bundle the app, this ensures the Metro config + // works correctly with Expo projects. + cliFile = new File(["node", "--print", "require.resolve('@expo/cli')"].execute(null, rootDir).text.trim()) + bundleCommand = "export:embed" } ``` ### `ios/.xcodeproj/project.pbxproj` In your `ios/.xcodeproj/project.pbxproj` file, replace the following scripts: #### `"Start Packager"` Remove the "Start Packager" script in SDK 50 and higher. The dev server must be started with `npx expo` before/after running the app. ``` - FD10A7F022414F080027D42C /* Start Packager */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Start Packager"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\nexport RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `$NODE_BINARY --print \"require('path').dirname(require.resolve('expo/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n"; - showEnvVarsInLog = 0; - }; ``` #### "Bundle React Native code and images" ``` + shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli')\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; ``` Alternatively, in the Xcode project, select the "Bundle React Native code and images" build phase and add the following modifications: ``` if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then source "$PODS_ROOT/../.xcode.env" fi if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then source "$PODS_ROOT/../.xcode.env.local" fi # The project root by default is one level up from the ios directory export PROJECT_ROOT="$PROJECT_DIR"/.. if [[ "$CONFIGURATION" = *Debug* ]]; then export SKIP_BUNDLING=1 fi + if [[ -z "$ENTRY_FILE" ]]; then + # Set the entry JS file using the bundler's entry resolution. + export ENTRY_FILE="$("$NODE_BINARY" -e "require('expo/scripts/resolveAppEntry')" "$PROJECT_ROOT" ios absolute | tail -n 1)" + fi + if [[ -z "$CLI_PATH" ]]; then + # Use Expo CLI + export CLI_PATH="$("$NODE_BINARY" --print "require.resolve('@expo/cli')")" + fi + if [[ -z "$BUNDLE_COMMAND" ]]; then + # Default Expo CLI command for bundling + export BUNDLE_COMMAND="export:embed" + fi `"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"` ``` > You can set `CLI_PATH`, `BUNDLE_COMMAND`, and `ENTRY_FILE` environment variables to overwrite these defaults. ### Custom entry file By default, React Native only supports using a root `index.js` file as the entry file (or platform-specific variation like `index.ios.js`). Expo projects allow using any entry file, but this requires addition bare setup. #### Development Development mode entry files can be enabled by using the [`expo-dev-client` package. Alternatively you can add the following configuration: In the `ios/[project]/AppDelegate.mm` file: ``` - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG - return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@".expo/.virtual-metro-entry"]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } ``` In the `android/app/src/main/java/**/MainApplication.java`: ``` @Override protected String getJSMainModuleName() { - return "index"; + return ".expo/.virtual-metro-entry"; } ``` #### Production In your `ios/.xcodeproj/project.pbxproj` file, replace the `"Bundle React Native code and images"` script to set `$ENTRY_FILE` according using Metro: ``` + shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli')\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; ``` The Android `app/build.gradle` must be configured to use Metro module resolution to find the root entry file. Modify the `react` config object: ``` + def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() react { + entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim()) } ``` --- # Expo Accelerometer `Accelerometer` from `expo-sensors` provides access to the device accelerometer sensor(s) and associated listeners to respond to changes in acceleration in three-dimensional space, meaning any movement or vibration. ## Installation `npx expo install expo-sensors` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. ## Usage Basic Accelerometer usage ``` 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 ( ``` Accelerometer: (in gs where 1g = 9.81 m/s^2) x: {x} y: {y} z: {z} {subscription ? 'On' : 'Off'} Slow Fast ``` ); } 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 ``` import { Accelerometer } from 'expo-sensors'; ``` ## Classes ### `Accelerometer` Type: Class extends `[DeviceSensor<[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)` | 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()` Returns the registered listeners count. Returns: `number` ### `getPermissionsAsync()` Checks user's permissions for accessing sensor. Returns: `[Promise<[PermissionResponse](#permissionresponse)>` ### `hasListeners()` Returns boolean which signifies if sensor has any listeners registered. Returns: `boolean` ### `isAvailableAsync()` > 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()` Removes all registered listeners. Returns: `void` ### `removeSubscription(subscription)` | Parameter | Type | Description | | --- | --- | --- | | subscription | `EventSubscription` | A subscription to remove. | Removes the given subscription. Returns: `void` ### `requestPermissionsAsync()` Asks the user to grant permissions for accessing sensor. Returns: `[Promise<[PermissionResponse](#permissionresponse)>` ### `setUpdateInterval(intervalMs)` | Parameter | Type | Description | | --- | --- | --- | | intervalMs | `number` | Desired interval in milliseconds between sensor updates. > Starting from Android 12 (API level 31), the system has a 200ms limit for each sensor updates. > > If you need an update interval less than 200ms, you should: > > * add `android.permission.HIGH_SAMPLING_RATE_SENSORS` to [app.json `permissions` field > * or if you are using bare workflow, add `` to AndroidManifest.xml. | Set the sensor update interval. Returns: `void` ## Interfaces ### `PermissionResponse` 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](#permissionexpiration)` | Determines time when the permission expires. | | granted | `boolean` | A convenience boolean that indicates if the permission is granted. | | status | `[PermissionStatus](#permissionstatus)` | Determines the status of the permission. | ## Types ### `AccelerometerMeasurement` 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` Literal Type: `union` Permission expiration time. Currently, all permissions are granted permanently. Acceptable values are: `'never'` | `number` ### `Subscription` A subscription object that allows to conveniently remove an event listener from the emitter. | Property | Type | Description | | --- | --- | --- | | remove | `() => void` | 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. | ## Enums ### `PermissionStatus` #### `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. --- # Expo AppleAuthentication `expo-apple-authentication` provides Apple authentication for iOS. It does not yet support Android or web. Any app that includes third-party authentication options must provide Apple authentication as an option to comply with App Store Review guidelines. For more information, see Apple authentication on the [Sign In with Apple website. ## Installation `npx expo install expo-apple-authentication` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. ## Configuration in app config You can configure `expo-apple-authentication` using its built-in [config plugin if you use config plugins in your project ([EAS Build or `npx expo run:[android|ios]`). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect. If your app does not use EAS Build, then you'll need to manually configure the package. ### Setup iOS project To enable the Sign In with Apple capability in your app, set the [`ios.usesAppleSignIn` property to `true` in your project's app config: app.json ``` { "expo": { ``` "ios": { "usesAppleSignIn": true } ``` } } ``` ### Example app.json with config plugin Running [EAS Build locally will use [iOS capabilities signing to enable the required capabilities before building. app.json ``` { "expo": { ``` "plugins": ["expo-apple-authentication"] ``` } } ``` Are you using this library in an existing React Native app? Apps that don't use [EAS Build must [manually configure the Apple Sign In capability for their bundle identifier. If you enable the Apple Sign In capability through the [Apple Developer Console, then be sure to add the following entitlements in your ios/\[app\]/\[app\].entitlements file: ``` com.apple.developer.applesignin Default ``` Also, set `CFBundleAllowMixedLocalizations` to `true` in your ios/\[app\]/Info.plist to ensure the sign-in button uses the device locale. ## Usage Apple Authentication Usage ``` 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, ], }); // signed in } catch (e) { if (e.code === 'ERR_REQUEST_CANCELED') { // handle that the user canceled the sign-in flow } else { // handle other errors } } }} /> ``` ); } const styles = StyleSheet.create({ container: { ``` flex: 1, alignItems: 'center', justifyContent: 'center', ``` }, button: { ``` width: 200, height: 44, ``` }, }); ``` ## Development and testing You can test this library in Expo Go on iOS without following any of the instructions above. However, you'll need to add the config plugin to use this library if you are using EAS Build. When you sign into Expo Go, the identifiers and values you receive will likely be different than what you'll receive in standalone apps. You can do limited testing of this library on the iOS Simulator. However, not all methods will behave the same as on a device, so we highly recommend testing on a real device when possible while developing. ## Verifying the Response from Apple Apple's response includes a signed JWT with information about the user. To ensure that the response came from Apple, you can cryptographically verify the signature with Apple's public key, which is published at [https://appleid.apple.com/auth/keys. This process is not specific to Expo. ## API ``` import * as AppleAuthentication from 'expo-apple-authentication'; ``` ## Component ### `AppleAuthenticationButton` 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()` 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 for more details. AppleAuthenticationButtonProps ### `buttonStyle` iOS tvOS Type: `[AppleAuthenticationButtonStyle](#appleauthenticationbuttonstyle)` The Apple-defined color scheme to use to display the button. ### `buttonType` iOS tvOS Type: `[AppleAuthenticationButtonType](#appleauthenticationbuttontype)` The type of button text to display ("Sign In with Apple" vs. "Continue with Apple"). ### `cornerRadius` iOS tvOS Optional Type: `number` The border radius to use when rendering the button. This works similarly to `style.borderRadius` in other Views. ### `onPress` iOS tvOS Type: `() => void` The method to call when the user presses the button. You should call `AppleAuthentication.signInAsync` in here. ### `style` iOS tvOS Optional Type: `StyleProp<[Omit<[ViewStyle, 'backgroundColor' | 'borderRadius'>>` The custom style to apply to the button. Should not include `backgroundColor` or `borderRadius` properties. #### Inherited Props * `[ViewProps` ## Methods ### `AppleAuthentication.getCredentialStateAsync(user)` 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` 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<[AppleAuthenticationCredentialState](#appleauthenticationcredentialstate)>` A promise that fulfills with an `AppleAuthenticationCredentialState` value depending on the state of the credential. ### `AppleAuthentication.isAvailableAsync()` 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)` iOS tvOS | Parameter | Type | Description | | --- | --- | --- | | options | `[AppleAuthenticationRefreshOptions](#appleauthenticationrefreshoptions)` | An `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<[AppleAuthenticationCredential](#appleauthenticationcredential)>` A promise that fulfills with an `AppleAuthenticationCredential` object after a successful authentication, and rejects with `ERR_REQUEST_CANCELED` if the user cancels the refresh operation. ### `AppleAuthentication.signInAsync(options)` iOS tvOS | Parameter | Type | Description | | --- | --- | --- | | options(optional) | `[AppleAuthenticationSignInOptions](#appleauthenticationsigninoptions)` | An optional `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, so that the data persists across app installs. You can use `AppleAuthenticationCredential.user` to identify the user, since this remains the same for apps released by the same developer. Returns: `[Promise<[AppleAuthenticationCredential](#appleauthenticationcredential)>` A promise that fulfills with an `AppleAuthenticationCredential` object after a successful authentication, and rejects with `ERR_REQUEST_CANCELED` if the user cancels the sign-in operation. ### `AppleAuthentication.signOutAsync(options)` iOS tvOS | Parameter | Type | Description | | --- | --- | --- | | options | `[AppleAuthenticationSignOutOptions](#appleauthenticationsignoutoptions)` | An `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` or [`refreshAsync` methods. Returns: `[Promise<[AppleAuthenticationCredential](#appleauthenticationcredential)>` A promise that fulfills with an `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)` iOS tvOS | Parameter | Type | | --- | --- | | listener | `() => void` | Returns: `EventSubscription` ## Types ### `AppleAuthenticationCredential` iOS tvOS The object type returned from a successful call to `AppleAuthentication.signInAsync()`, `AppleAuthentication.refreshAsync()`, or `AppleAuthentication.signOutAsync()` which contains all of the pertinent user and credential information. > See: [Apple Documentation 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` 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` | \- | ### `AppleAuthenticationRefreshOptions` iOS tvOS The options you can supply when making a call to `AppleAuthentication.refreshAsync()`. You must include the ID string of the user whose credentials you'd like to refresh. > See: [Apple Documentation 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. | | user | `string` | \- | ### `AppleAuthenticationSignInOptions` iOS tvOS The options you can supply when making a call to `AppleAuthentication.signInAsync()`. None of these options are required. > See: [Apple Documentation 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. | | 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. | ### `AppleAuthenticationSignOutOptions` iOS tvOS The options you can supply when making a call to `AppleAuthentication.signOutAsync()`. You must include the ID string of the user to sign out. > See: [Apple Documentation 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. | | user | `string` | \- | ### `Subscription` iOS tvOS A subscription object that allows to conveniently remove an event listener from the emitter. | Property | Type | Description | | --- | --- | --- | | remove | `() => void` | 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. | ## Enums ### `AppleAuthenticationButtonStyle` iOS tvOS An enum whose values control which pre-defined color scheme to use when rendering an `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` iOS tvOS An enum whose values control which pre-defined text to use when rendering an `AppleAuthenticationButton`. #### `SIGN_IN` `AppleAuthenticationButtonType.SIGN_IN = 0` "Sign in with Apple" #### `CONTINUE` `AppleAuthenticationButtonType.CONTINUE = 1` "Continue with Apple" #### `SIGN_UP` iOS 13.2+ `AppleAuthenticationButtonType.SIGN_UP = 2` "Sign up with Apple" ### `AppleAuthenticationCredentialState` iOS tvOS An enum whose values specify state of the credential when checked with `AppleAuthentication.getCredentialStateAsync()`. > See: [Apple Documentation for more details. #### `REVOKED` `AppleAuthenticationCredentialState.REVOKED = 0` #### `AUTHORIZED` `AppleAuthenticationCredentialState.AUTHORIZED = 1` #### `NOT_FOUND` `AppleAuthenticationCredentialState.NOT_FOUND = 2` #### `TRANSFERRED` `AppleAuthenticationCredentialState.TRANSFERRED = 3` ### `AppleAuthenticationOperation` 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` iOS tvOS An enum whose values specify scopes you can request when calling `AppleAuthentication.signInAsync()`. > 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 for more details. #### `FULL_NAME` `AppleAuthenticationScope.FULL_NAME = 0` #### `EMAIL` `AppleAuthenticationScope.EMAIL = 1` ### `AppleAuthenticationUserDetectionStatus` 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 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. ## Error codes Most of the error codes match the official [Apple Authorization errors. | Code | Description | | --- | --- | | ERR\_INVALID\_OPERATION | An invalid authorization operation has been performed. | | ERR\_INVALID\_RESPONSE | The authorization request received an invalid response. | | ERR\_INVALID\_SCOPE | An invalid [`AppleAuthenticationScope` was passed in. | | ERR\_REQUEST\_CANCELED | The user canceled the authorization attempt. | | ERR\_REQUEST\_FAILED | The authorization attempt failed. See the error message for additional information. | | ERR\_REQUEST\_NOT\_HANDLED | The authorization request wasn't correctly handled. | | ERR\_REQUEST\_NOT\_INTERACTIVE | The authorization request isn't interactive. | | ERR\_REQUEST\_UNKNOWN | The authorization attempt failed for an unknown reason. | --- # Expo Application `expo-application` provides useful information about the native application's ID, app name, and build version at runtime. ## Installation `npx expo install expo-application` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. ## API ``` import * as Application from 'expo-application'; ``` ## Constants ### `Application.applicationId` 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` 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` 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` 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 Android: `"114"`, iOS: `"2.11.0"` ## Methods ### `Application.getAndroidId()` Android Gets the value of [`Settings.Secure.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. 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 official docs for more information. Returns: `string` Example `"dd96dec43fb81c97"` ### `Application.getInstallationTimeAsync()` 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`. * On iOS, this method uses the [`NSFileCreationDate` of the app's document root directory. * On web, this method returns `null`. Returns: `[Promise<[Date>` A `Promise` that fulfills with a `Date` object that specifies the time the app was installed on the device. Example ``` await Application.getInstallationTimeAsync(); // 2019-07-18T18:08:26.121Z ``` ### `Application.getInstallReferrerAsync()` Android Gets the referrer URL of the installed app with the [`Install Referrer API` 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 ``` await Application.getInstallReferrerAsync(); // "utm_source=google-play&utm_medium=organic" ``` ### `Application.getIosApplicationReleaseTypeAsync()` iOS Gets the iOS application release type. Returns: `[Promise<[ApplicationReleaseType](#applicationreleasetype)>` A `Promise` which fulfills with an `ApplicationReleaseType`. ### `Application.getIosIdForVendorAsync()` iOS Gets the iOS "identifier for vendor" ([IDFV) 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 ``` await Application.getIosIdForVendorAsync(); // "68753A44-4D6F-1226-9C60-0050E4C00067" ``` ### `Application.getIosPushNotificationServiceEnvironmentAsync()` iOS Gets the current [Apple Push Notification (APN) service environment. Returns: `[Promise<[PushNotificationServiceEnvironment](#pushnotificationserviceenvironment)>` 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()` Android Gets the last time the app was updated from the Google Play Store. Returns: `[Promise<[Date>` A `Promise` that fulfills with a `Date` object that specifies the last time the app was updated via the Google Play Store. Example ``` await Application.getLastUpdateTimeAsync(); // 2019-07-18T21:20:16.887Z ``` ## Types ### `PushNotificationServiceEnvironment` iOS Literal Type: `union` Maps to the [`aps-environment` key in the native target's registered entitlements. Acceptable values are: `'development'` | `'production'` | `null` ## Enums ### `ApplicationReleaseType` 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` ## Error codes | Code | Description | | --- | --- | | `ERR_APPLICATION_PACKAGE_NAME_NOT_FOUND` | Error code thrown by `getInstallationTimeAsync` and `getLastUpdateTimeAsync`. This may be thrown if the package information or package name could not be retrieved. | | `ERR_APPLICATION_INSTALL_REFERRER_UNAVAILABLE` | The current Play Store app doesn't provide the installation referrer API, or the Play Store may not be installed. This error code may come up when testing on an AVD that doesn't come with the Play Store pre-installed, such as the Google Pixel 3 and Nexus 6. | | `ERR_APPLICATION_INSTALL_REFERRER_CONNECTION` | A connection could not be established to the Google Play Store. | | `ERR_APPLICATION_INSTALL_REFERRER_REMOTE_EXCEPTION` | A `RemoteException` was thrown after a connection was established to the Play Store. This may happen if the process hosting the remote object is no longer available, which usually means the process crashed. See [this StackOverflow answer on `RemoteException` for more information. | | `ERR_APPLICATION_INSTALL_REFERRER` | General default case error code for the `getInstallReferrerAsync` method. This error code will be thrown if an exception occurred when getting the install referrer, but the exception was none of the more precise errors. The [`responseCode` is provided along with the error. | | `ERR_APPLICATION_INSTALL_REFERRER_SERVICE_DISCONNECTED` | Connection to the install referrer service was lost. This error is thrown when an attempt was made to connect and set up the install referrer service, but the connection was lost. See the [Android documentation for more information. | --- # Expo Asset `expo-asset` provides an interface to Expo's asset system. An asset is any file that lives alongside the source code of your app that the app needs at runtime. Examples include images, fonts, and sounds. Expo's asset system integrates with React Native's, so that you can refer to files with `require('path/to/file')`. This is how you refer to static image files in React Native for use in an `Image` component, for example. Check out React Native's [documentation on static image resources for more information. This method of referring to static image resources works out of the box with Expo. ## Installation `npx expo install expo-asset` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. ## Configuration in app config You can configure `expo-asset` using its built-in [config plugin if you use config plugins in your project ([EAS Build or `npx expo run:[android|ios]`). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect. ### Example app.json with config plugin app.json ``` { "expo": { ``` "plugins": [ "expo-asset", { "assets": ["path/to/file.png", "path/to/directory"] } ``` } } ``` ### Configurable properties | Name | Default | Description | | --- | --- | --- | | `assets` | `` | An array of asset files or directories to link to the native project. The paths should be relative to the project root so that the file names, whether specified directly or using a directory, will become the resource names. Supported file types: * Images: `.png`, `.jpg`, `.gif` * Media: `.mp4`, `.mp3`, `.lottie` * SQLite database files: `.db` > Note: To import an existing database file (`.db`), see instructions in [SQLite API reference. For other file types such as `.lottie`, see [how to add a file extension to `assetExts` in metro config. | ### Usage Learn more about how to use the `expo-asset` config plugin to embed an asset file in your project in [Load an asset at build time. ## API ``` import { Asset } from 'expo-asset'; ``` ## Hooks ### `useAssets(moduleIds)` 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 ``` const [assets, error] = useAssets([require('path/to/asset.jpg'), require('path/to/other.png')]); return assets ? : null; ``` ## Classes ### `Asset` 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` tvOS Web Type: `boolean` Default: `false` Whether the asset has finished downloading from a call to `downloadAsync()`. ### `hash` tvOS Web Read Only Literal type: `union` Default: `null` The MD5 hash of the asset's data. Acceptable values are: `null` | `string` ### `height` 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: `null` | `number` ### `localUri` tvOS Web Literal type: `union` Default: `null` If the asset has been downloaded (by calling `downloadAsync()`), the `file://` URI pointing to the local file on the device that contains the asset data. Acceptable values are: `null` | `string` ### `name` 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` tvOS Web Read Only Type: `string` The extension of the asset filename. ### `uri` 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` 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: `null` | `number` Asset Methods ### `downloadAsync()` 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` 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. Returns: `[Promise<[Asset>` Returns a Promise which fulfills with an `Asset` instance. ### `fromMetadata(meta)` tvOS Web | Parameter | Type | | --- | --- | | meta | `[AssetMetadata](#assetmetadata)` | Returns: `[Asset` ### `fromModule(virtualAssetModule)` 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` instance representing an asset given its module or URL. Returns: `[Asset` The `Asset` instance for the asset. ### `fromURI(uri)` tvOS Web | Parameter | Type | | --- | --- | | uri | `string` | Returns: `[Asset` ### `loadAsync(moduleId)` 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<[Asset>` Returns a Promise that fulfills with an array of `Asset`s when the asset(s) has been saved to disk. Example ``` const [{ localUri }] = await Asset.loadAsync(require('./assets/snack-icon.png')); ``` ## Types ### `AssetDescriptor` tvOS Web | Property | Type | Description | | --- | --- | --- | | hash(optional) | `string | null` | \- | | height(optional) | `number | null` | \- | | name | `string` | \- | | type | `string` | \- | | uri | `string` | \- | | width(optional) | `number | null` | \- | ### `AssetMetadata` tvOS Web Type: `[Pick<[PackagerAsset, 'httpServerLocation' | 'name' | 'hash' | 'type' | 'scales' | 'width' | 'height'>` extended by: | Property | Type | Description | | --- | --- | --- | | fileHashes(optional) | `string` | \- | | fileUris(optional) | `string` | \- | | uri(optional) | `string` | \- | --- # AsyncStorage An asynchronous, unencrypted, persistent, key-value storage API. ## Installation `npx expo install @react-native-async-storage/async-storage` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. Then, follow the [installation instructions provided in the library's README or documentation. ## Usage See [Async Storage's documentation for usage instructions]. --- # Expo Audio (expo-audio) > This page documents an upcoming version of the Audio library. Expo Audio is currently in alpha and subject to breaking changes. `expo-audio` is a cross-platform audio library for accessing the native audio capabilities of the device. Note that audio automatically stops if headphones/bluetooth audio devices are disconnected. ## Installation `npx expo install expo-audio` If you are installing this in an [existing React Native app, make sure to [install `expo` in your project. ## Configuration in app config You can configure `expo-audio` using its built-in [config plugin if you use config plugins in your project ([EAS Build or `npx expo run:[android|ios]`). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect. If your app does not use EAS Build, then you'll need to manually configure the package. ### Example app.json with config plugin app.json ``` { "expo": { ``` "plugins": [ "expo-audio", { "microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone." } ``` } } ``` ### Configurable properties | Name | Default | Description | | --- | --- | --- | | `microphonePermission` | `"Allow $(PRODUCT_NAME) to access your microphone"` | Only for: iOS A string to set the `NSMicrophoneUsageDescription` permission message. | ## Usage ### Playing sounds Playing sounds ``` 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 ( ```