安卓构建流程
了解如何在 EAS Build 上构建 Android 项目。
本页面介绍了使用 EAS Build 构建 Android 项目的过程。如果你对构建服务的实现细节感兴趣,可能会想阅读此内容。
🌐 This page describes the process of building Android projects with EAS Build. You may want to read this if you are interested in the implementation details of the build service.
构建过程
🌐 Build process
让我们仔细看看使用 EAS Build 构建 Android 项目的步骤。我们将首先在本地机器上运行一些步骤来准备项目,然后在远程服务上构建项目。
🌐 Let's take a closer look at the steps for building Android projects with EAS Build. We'll first run some steps on your local machine to prepare the project, and then we'll build the project on a remote service.
本地步骤
🌐 Local steps
第一阶段发生在你的电脑上。EAS CLI 负责完成以下步骤:
🌐 The first phase happens on your computer. EAS CLI is in charge of completing the following steps:
- 如果在 eas.json 中将
cli.requireCommit设置为true,请检查 git 索引是否干净——这意味着没有未提交的更改。如果不干净,EAS CLI 会提供一个选项,让你提交本地更改或中止构建过程。 - 除非
builds.android.PROFILE_NAME.withoutCredentials被设置为true,否则请准备构建所需的凭据。- 根据
builds.android.PROFILE_NAME.credentialsSource的值,凭证将从本地 credentials.json 文件或 EAS 服务器获取。如果选择remote模式但尚未存在凭证,则会提示你生成一个新的密钥库。
- 根据
- 创建一个包含仓库副本的 tar 包。实际行为取决于你使用的 VCS 工作流。
- 将项目 tarball 上传到私有 AWS S3 存储桶并将构建请求发送到 EAS Build。
远程步骤
🌐 Remote steps
接下来,当 EAS Build 收到你的请求时会发生以下情况:
🌐 Next, this is what happens when EAS Build picks up your request:
- 为构建创建一个新的 Docker 容器。
- 每个构建都有自己的新容器,其中安装了所有构建工具(Java JDK、Android SDK、NDK 等)。
- 从私有 AWS S3 存储桶下载项目 tarball 并解压。
- 如果设置了
NPM_TOKEN,请创建 .npmrc 。 - 如果在 package.json 中定义了,运行
eas-build-pre-install脚本。 - 在项目根目录运行
npm install(如果存在yarn.lock,则运行yarn install)。 - 运行
npx expo-doctor来诊断项目配置中的潜在问题。 - 托管项目的额外步骤:运行
npx expo prebuild将项目转换为裸项目。此步骤将使用有版本控制的 Expo CLI。 - 恢复在构建配置中由
cache.key值标识的先前保存的缓存。 - 如果在 package.json 中定义了,运行
eas-build-post-install脚本。 - 恢复密钥库(如果它包含在构建请求中)。
- 将签名配置注入到 build.gradle 中。
- 在项目的 android 目录下运行
./gradlew COMMAND。COMMAND是在你的 eas.json 中builds.android.PROFILE_NAME.gradleCommand定义的命令。默认值是:app:bundleRelease,它会生成 AAB(Android 应用包)。
- 已弃用: 如果在 package.json 中定义了,运行
eas-build-pre-upload-artifacts脚本。 - 存储在构建配置文件中定义的文件和目录缓存。后续构建将会恢复此缓存。
- 将应用存档上传到 AWS S3。
- 可以在 eas.json 的
builds.android.PROFILE_NAME.applicationArchivePath中配置工件路径。默认值为android/app/build/outputs/**/*.{apk,aab}。我们使用 glob 模式 进行模式匹配。
- 可以在 eas.json 的
- 如果构建成功:如果在 package.json 中定义了,请运行
eas-build-on-success脚本。 - 如果构建失败:请运行 package.json 中定义的
eas-build-on-error脚本(如果有的话)。 - 如果在 package.json 中定义了,请运行
eas-build-on-complete脚本。EAS_BUILD_STATUS环境变量被设置为finished或errored。 - 如果在构建配置中指定了
buildArtifactPaths,请将构建产物归档上传到私有的 AWS S3 存储桶。
项目自动配置
🌐 Project auto-configuration
每次你想要构建一个新的 Android 应用二进制文件时,我们都会验证项目是否已正确设置,以便我们可以在我们的服务器上顺利运行构建过程。这主要适用于裸项目,但在构建托管项目时也会执行类似的步骤。
🌐 Every time you want to build a new Android app binary, we validate that the project is set up correctly so we can seamlessly run the build process on our servers. This mainly applies to bare projects, but similar steps are run when building managed projects.
安卓密钥库
🌐 Android keystore
Android要求你使用证书来签署你的应用。该证书存储在你的密钥库中。Google Play商店根据证书识别应用。这意味着如果你丢失了密钥库,可能无法在商店中更新应用。然而,通过Play应用签名,你可以降低丢失密钥库的风险。
🌐 Android requires you to sign your application with a certificate. That certificate is stored in your keystore. The Google Play Store identifies applications based on the certificate. This means that if you lose your keystore, you may not be able to update your application in the store. However, with Play App Signing, you can mitigate the risk of losing your keystore.
你应用的密钥库应该保密。在任何情况下都不应将其提交到你的代码仓库。 唯一的例外是调试密钥库,因为我们不会使用它们上传应用到 Google Play 商店。
🌐 Your application's keystore should be kept private. Under no circumstances should you check it in to your repository. Debug keystores are the only exception because we don't use them for uploading apps to the Google Play Store.
配置 Gradle
🌐 Configuring Gradle
你的应用二进制文件需要使用密钥库进行签名。由于我们在远程服务器上构建项目,因此我们必须想出一种方法向 Gradle 提供凭据,而出于安全原因,这些凭据不会被提交到你的代码库。在其中一个远程步骤中,我们会将签名配置注入到你的 build.gradle 中。EAS Build 会创建包含以下内容的 android/app/eas-build.gradle 文件:
🌐 Your app binary needs to be signed with a keystore. Since we're building the project on a remote server, we had to come up with a way to provide Gradle with credentials which aren't, for security reasons, checked in to your repository. In one of the remote steps, we inject the signing configuration into your build.gradle. EAS Build creates the android/app/eas-build.gradle file with the following contents:
// Build integration with EAS import java.nio.file.Paths android { signingConfigs { release { // This is necessary to avoid needing the user to define a release signing config manually // If no release config is defined, and this is not present, build for assembleRelease will crash } } buildTypes { release { // This is necessary to avoid needing the user to define a release build type manually } debug { // This is necessary to avoid needing the user to define a debug build type manually } } } tasks.whenTaskAdded { android.signingConfigs.release { def credentialsJson = rootProject.file("../credentials.json"); def credentials = new groovy.json.JsonSlurper().parse(credentialsJson) def keystorePath = Paths.get(credentials.android.keystore.keystorePath); def storeFilePath = keystorePath.isAbsolute() ? keystorePath : rootProject.file("..").toPath().resolve(keystorePath); storeFile storeFilePath.toFile() storePassword credentials.android.keystore.keystorePassword keyAlias credentials.android.keystore.keyAlias if (credentials.android.keystore.containsKey("keyPassword")) { keyPassword credentials.android.keystore.keyPassword } else { // key password is required by Gradle, but PKCS keystores don't have one // using the keystore password seems to satisfy the requirement keyPassword credentials.android.keystore.keystorePassword } } android.buildTypes.release { signingConfig android.signingConfigs.release } android.buildTypes.debug { signingConfig android.signingConfigs.release } }
最重要的部分是 release 签名配置。它被配置为从项目根目录的 credentials.json 文件中读取密钥库和密码。即使你不需要自己创建这个文件,它也会在构建运行之前由 EAS Build 创建并填充你的凭据。
🌐 The most important part is the release signing config. It's configured to read the keystore and passwords from the credentials.json file at the project root. Even though you're not required to create this file on your own, it's created and populated with your credentials by EAS Build before running the build.
该文件在 android/app/build.gradle 中这样导入:
🌐 This file is imported in android/app/build.gradle like this:
// ... apply from: "./eas-build.gradle"