在同一设备上安装应用变体
编辑页面
了解如何在同一设备上安装应用的多个变体。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
在创建开发、预览和生产构建时,通常会在同一设备上同时安装这些构建变体。这使你能够进行开发、预览应用的下一个版本,并在设备上运行生产版本,而无需卸载并重新安装应用。
本指南提供了在同一设备上安装和使用多个(开发和生产)变体所需的步骤。
前提条件
要在设备上安装应用的多个变体,每个变体都必须具有唯一的 Application ID(Android) 或 Bundle Identifier(iOS)。
配置开发和生产变体
你已经使用 Expo 工具创建了一个项目,现在你想创建一个开发构建和一个生产构建。你项目的 app.json 可能具有如下配置:
{ "expo": { "name": "MyApp", "slug": "my-app", "ios": { "bundleIdentifier": "com.myapp" }, "android": { "package": "com.myapp" } } }
如果你的项目已配置 EAS Build,eas.json 中也会有如下所示的类似配置:
{ "build": { "development": { "developmentClient": true }, "production": {} } }
将 app.json 转换为 app.config.js
要在同一设备上安装应用的多个变体,请将 app.json 重命名为 app.config.js,并按如下所示导出配置:
export default { name: 'MyApp', slug: 'my-app', ios: { bundleIdentifier: 'com.myapp', }, android: { package: 'com.myapp', }, };
在 app.config.js 中,添加一个名为 IS_DEV 的环境变量,以便根据该变量切换每个变体的 android.package 和 ios.bundleIdentifier:
const IS_DEV = process.env.APP_VARIANT === 'development'; export default { name: IS_DEV ? 'MyApp (开发版)' : 'MyApp', slug: 'my-app', ios: { bundleIdentifier: IS_DEV ? 'com.myapp.dev' : 'com.myapp', }, android: { package: IS_DEV ? 'com.myapp.dev' : 'com.myapp', } };
在上面的示例中,环境变量 IS_DEV 用于区分开发环境和生产环境。根据它的值,会为每个变体设置不同的 Application ID 或 Bundle Identifier。
其他应用变体自定义
你可以按变体自定义应用的其他方面。你可以使用与上面相同的方法,替换你之前在 app.json 中使用的任何配置。
示例:
- 如果你使用的库要求你向外部服务注册应用标识符才能使用其 SDK,例如 Google Maps 或 Firebase Cloud Messaging(FCM),那么你需要为
android.package和ios.bundleIdentifier分别配置独立的 API 设置。 - 如果你在使用 开发构建,你可以配置
expo-dev-client插件,在非开发构建中禁用 Expo CLI 和 EAS Update 二维码使用的应用 scheme。这样可以确保这些 URL 无论设备默认设置如何,都会始终启动开发构建:
plugins: [ [ 'expo-dev-client', { addGeneratedScheme: !!IS_DEV, }, ], ],
EAS Build 的配置
在 eas.json 中,使用 env 属性设置 APP_VARIANT 环境变量,以便使用 development 配置运行构建:
{ "build": { "development": { "developmentClient": true, "env": { "APP_VARIANT": "development" } }, "production": {} } }
现在,当你运行 eas build --profile development 时,在本地以及 EAS Build 构建器上评估 app.config.js 时,环境变量 APP_VARIANT 都会被设置为 development。
使用开发服务器
当你启动开发服务器时,需要运行 APP_VARIANT=development npx expo start(如果你使用 Windows,则使用对应的平台命令)。
为此,你可以在 package.json 中添加以下脚本:
{ "scripts": { "dev": "APP_VARIANT=development npx expo start" } }
使用生产变体
当你运行 eas build --profile production 时,环境变量 APP_VARIANT 不会被设置,构建会作为生产变体运行。
注意:如果你使用 EAS Update 发布应用的 JavaScript 更新,在运行
eas update命令时,应谨慎为你发布的应用变体设置正确的环境变量。更多信息请参阅 EAS Build 的 环境变量和密钥。
在现有(裸)React Native 项目中
如果你希望将你的 应用配置文件 作为应用配置的唯一可信来源(包括变体的 bundle identifier 和 package name),你需要迁移到 Continuous Native Generation (CNG) 并将 android 和 ios 目录添加到 .gitignore 文件中。如果你最初是从 React Native CLI 项目开始,并添加了自定义原生代码,这一点尤其重要。这可以确保原生项目配置不会优先于你的应用配置,尤其是在使用 bundle ID 查找行为时。否则,你可能会遇到运行了错误的应用变体或开发构建未被正确检测的问题。或者,你也可以按下文所述显式使用 Android flavors 和 iOS schemes。
Android
在 android/app/build.gradle 中,为你想要构建的 eas.json 中的每个构建配置创建一个单独的 flavor。
android { %%placeholder-start%%... %%placeholder-end%% flavorDimensions "env" productFlavors { production { dimension "env" applicationId 'com.myapp' } development { dimension "env" applicationId 'com.myapp.dev' } } %%placeholder-start%%... %%placeholder-end%% }
注意:目前,EAS CLI 仅支持
applicationId字段。如果你在productFlavors或buildTypes部分中使用applicationIdSuffix,那么该值将无法被正确检测。
通过在 eas.json 中指定 gradleCommand,将 Android flavors 分配给 EAS Build 配置:
{ "build": { "development": { "android": { "gradleCommand": ":app:assembleDevelopmentDebug" } }, "production": { "android": { "gradleCommand": ":app:bundleProductionRelease" } } } }
默认情况下,每个 flavor 都可以以 debug 或 release 模式构建。如果你想将某些 flavor 限制为特定模式,请查看下面的片段,并修改 build.gradle。
android { %%placeholder-start%%... %%placeholder-end%% variantFilter { variant -> def validVariants = [ ["production", "release"], ["development", "debug"], ] def buildTypeName = variant.buildType*.name def flavorName = variant.flavors*.name def isValid = validVariants.any { flavorName.contains(it[0]) && buildTypeName.contains(it[1]) } if (!isValid) { setIgnore(true) } } %%placeholder-start%%... %%placeholder-end%% }
到这里为止,其余配置并非 EAS 特有,它与任何使用 flavors 的 Android 项目相同。你可能希望应用到项目中的一些常见配置如下:
- 要更改使用 development 配置构建的应用名称,请创建 android/app/src/development/res/value/strings.xml 文件:
android/app/src/development/res/value/strings.xml
<resources> <string name="app_name">MyApp - 开发版</string> </resources> - 要更改使用 development 配置构建的应用图标,请创建 android/app/src/development/res/mipmap-* 目录,并放入相应资源(你可以从 android/app/src/main/res 复制它们并替换图标文件)。
- 要为特定 flavor 指定 google-services.json,请将其放在 android/app/src/{flavor}/google-services.json 文件中。
- 要配置 sentry,请在 android/app/build.gradle 中添加
project.ext.sentryCli = [ flavorAware: true ],并将你的属性文件命名为 android/sentry-{flavor}-{buildType}.properties(例如,android/sentry-production-release.properties)
iOS
在 eas.json 中为每个构建配置分配不同的 scheme:
{ "build": { "development": { "ios": { "buildConfiguration": "Debug", "scheme": "myapp-dev" } }, "production": { "ios": { "buildConfiguration": "Release", "scheme": "myapp" } } } }
Podfile 应该有如下所示的 target 定义:
target 'myapp' do %%placeholder-start%%... %%placeholder-end%% end
将其替换为一个抽象 target,把通用配置从旧 target 中复制过来:
abstract_target 'common' do # 在这里放置通用的 target 配置 target 'myapp' do end target 'myapp-dev' do end end
在 Xcode 中打开项目,点击导航面板中的项目名称,右键点击现有 target,然后点击“Duplicate”:
将 target 重命名为更有意义的名称,例如,将 myapp copy -> myapp-dev。
为新 target 配置一个 scheme:
- 前往
Product->Scheme->Manage schemes。 - 在列表中找到 scheme
myapp copy。 - 将 scheme 名称
myapp copy->myapp-dev。 - 默认情况下,新 scheme 应该会被标记为共享,但 Xcode 不会创建
.xcscheme文件。为了解决这个问题,取消勾选“Shared”复选框,然后再重新勾选;之后新的.xcscheme文件应该会出现在 ios/myapp.xcodeproj/xcshareddata/xcschemes 目录中。
默认情况下,新创建的 target 有单独的 Info.plist 文件(在上面的示例中,它是 ios/myapp copy-Info.plist)。为了简化项目,我们建议所有 target 使用同一个文件:
- 删除 ./ios/myapp copy-Info.plist。
- 点击新 target。
- 进入
Build Settings选项卡。 - 找到
Packaging部分。 - 更改 Info.plist 的值 - myapp copy-Info.plist -> myapp/Info.plist。
- 更改
Product Bundle Identifier。
要更改显示名称:
- 打开 Info.plist 并添加键
Bundle display name,其值为$(DISPLAY_NAME)。 - 打开两个 target 的
Build Settings,找到User-Defined部分。 - 添加键
DISPLAY_NAME,值为你希望该 target 使用的名称。
要更改应用图标:
- 创建一个新的图像集(你可以基于当前图标的现有图像集创建,通常名为
AppIcon) - 打开你想要更改图标的 target 的
Build Settings。 - 找到
Asset Catalog Compiler - Options部分。 - 将
Primary App Icon Set Name更改为新的图像集名称。