首页指南参考教程

安卓构建流程

了解如何在 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:

  1. 如果 eas.json 中 cli.requireCommit 设置为 true,检查 git 索引是否干净 - 这意味着不存在任何未提交的更改。如果不干净,EAS CLI 将提供一个选项来为你提交本地更改或中止构建过程。

    ¥If cli.requireCommit is set to true in eas.json, check if the git index is clean - this means that there aren't any uncommitted changes. If it's not clean, EAS CLI will provide an option to commit local changes for you or abort the build process.

  2. 准备构建所需的凭据,除非 builds.android.PROFILE_NAME.withoutCredentials 设置为 true

    ¥Prepare the credentials needed for the build unless builds.android.PROFILE_NAME.withoutCredentials is set to true.

    • 根据 builds.android.PROFILE_NAME.credentialsSource 的值,凭证是从本地凭据.json 文件或 EAS 服务器获取的。如果选择 remote 模式但尚不存在凭据,系统会提示你生成新的密钥库。

      ¥Depending on the value of builds.android.PROFILE_NAME.credentialsSource, the credentials are obtained from either the local credentials.json file or from the EAS servers. If the remote mode is selected but no credentials exist yet, you're prompted to generate a new keystore.

  3. 创建包含存储库副本的 tarball。实际行为取决于你使用的 视频控制系统工作流程

    ¥Create a tarball containing a copy of the repository. Actual behavior depends on the VCS workflow you are using.

  4. 将项目 tarball 上传到私有 AWS S3 存储桶并将构建请求发送到 EAS Build。

    ¥Upload the project tarball to a private AWS S3 bucket and send the build request to EAS Build.

远程步骤

¥Remote steps

接下来,当 EAS Build 收到你的请求时会发生以下情况:

¥Next, this is what happens when EAS Build picks up your request:

  1. 为构建创建一个新的 Docker 容器。

    ¥Create a new Docker container for the build.

    • 每个构建都有自己的新容器,其中安装了所有构建工具(Java JDK、Android SDK、NDK 等)。

      ¥Every build gets its own fresh container with all build tools installed there (Java JDK, Android SDK, NDK, and so on).

  2. 从私有 AWS S3 存储桶下载项目 tarball 并解压。

    ¥Download the project tarball from a private AWS S3 bucket and unpack it.

  3. 如果设置了 NPM_TOKEN,则为 创建.npmrc

    ¥Create .npmrc if NPM_TOKEN is set.

  4. 从 package.json 运行 eas-build-pre-install 脚本(如果已定义)。

    ¥Run the eas-build-pre-install script from package.json if defined.

  5. 在项目根目录中运行 npm install(如果 yarn.lock 存在,则运行 yarn install)。

    ¥Run npm install in the project root (or yarn install if yarn.lock exists).

  6. 运行 npx expo-doctor 来诊断项目配置的潜在问题。

    ¥Run npx expo-doctor to diagnose potential issues with your project configuration.

  7. 托管项目的附加步骤:运行 npx expo prebuild 将项目转换为裸项目。此步骤将使用版本化的 Expo CLI。

    ¥Additional step for managed projects: Run npx expo prebuild to convert the project to a bare one. This step will use the versioned Expo CLI.

  8. 恢复以前保存的由 建立档案 中的 cache.key 值标识的缓存。

    ¥Restore a previously saved cache identified by the cache.key value in the build profile.

  9. 从 package.json 运行 eas-build-post-install 脚本(如果已定义)。

    ¥Run the eas-build-post-install script from package.json if defined.

  10. 恢复密钥库(如果它包含在构建请求中)。

    ¥Restore the keystore (if it was included in the build request).

  11. 注入签名 配置到 build.gradle

    ¥Inject the signing configuration into build.gradle.

  12. 在项目内的 android 目录中运行 ./gradlew COMMAND

    ¥Run ./gradlew COMMAND in the android directory inside your project.

    • COMMAND 是在 builds.android.PROFILE_NAME.gradleCommand 处的 eas.json 中定义的命令。它默认为 :app:bundleRelease,它生成 AAB(Android 应用包)。

      ¥COMMAND is the command defined in your eas.json at builds.android.PROFILE_NAME.gradleCommand. It defaults to :app:bundleRelease which produces the AAB (Android App Bundle).

  13. 已弃用:从 package.json 运行 eas-build-pre-upload-artifacts 脚本(如果已定义)。

    ¥Deprecated: Run the eas-build-pre-upload-artifacts script from package.json if defined.

  14. 存储 建立档案.conf 中定义的文件和目录的缓存。后续构建将恢复此缓存。

    ¥Store a cache of files and directories defined in the build profile. Subsequent builds will restore this cache.

  15. 将应用存档上传到 AWS S3。

    ¥Upload the application archive to AWS S3.

    • 工件路径可以在 builds.android.PROFILE_NAME.applicationArchivePath 处的 eas.json 中配置。默认为 android/app/build/outputs/**/*.{apk,aab}。我们使用 fast-glob 包进行模式匹配。

      ¥The artifact path can be configured in eas.json at builds.android.PROFILE_NAME.applicationArchivePath. It defaults to android/app/build/outputs/**/*.{apk,aab}. We're using the fast-glob package for pattern matching.

  16. 如果构建成功:如果已定义,则运行 package.json 中的 eas-build-on-success 脚本。

    ¥If the build was successful: run the eas-build-on-success script from package.json if defined.

  17. 如果构建失败:如果已定义,则运行 package.json 中的 eas-build-on-error 脚本。

    ¥If the build failed: run the eas-build-on-error script from package.json if defined.

  18. 从 package.json 运行 eas-build-on-complete 脚本(如果已定义)。EAS_BUILD_STATUS 环境变量设置为 finishederrored

    ¥Run the eas-build-on-complete script from package.json if defined. The EAS_BUILD_STATUS env variable is set to either finished or errored.

  19. 如果在构建配置文件中指定了 buildArtifactPaths,则将构建工件存档上传到私有 AWS S3 存储桶。

    ¥Upload the build artifacts archive to a private AWS S3 bucket if buildArtifactPaths is specified in the build profile.

项目自动配置

¥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 商店根据证书识别应用。这意味着如果你丢失了密钥库,你可能无法在商店中更新你的应用。但是,使用 播放应用签名,你可以降低丢失密钥库的风险。

¥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:

android/app/eas-build.gradle
// 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:

android/app/build.gradle
// ...

apply from: "./eas-build.gradle"
Expo 中文网 - 粤ICP备13048890号