亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

全部開發者教程

Android Studio 中使用命令行構建應用

前面的小節我們介紹了通過圖形界面如何構建和運行我們的應用,從本小結我們學習如何在命令行中構建我們的應用。

1. 關于構建類型

1.1 關于 Gradle 封裝容器

在命令行中構建應用,我們使用的是 Gradle 封裝容器,它可作為 Windows 的批處理文件 (gradlew.bat) 和 Linux 與 Mac 的 shell 腳本 (gradlew) 使用,而且我們可以從使用 Android Studio 創建的每個項目的根目錄啟動該工具。

我們可以使用 Gradle 封裝容器命令行工具執行 Android 項目可用的所有構建任務。要使用封裝容器運行任務,請在終端窗口中(在 Android Studio 中,依次選擇 View > Tool Windows > Terminal)使用下列命令之一:

  • 在 Windows 上:
gradlew task-name
  • 在 Mac 或 Linux 上:
./gradlew task-name

Tips:task-name是代指具體的 Gradle 任務名稱。

如需查看項目的所有可用構建任務的列表,請執行如下命令:

gradlew tasks

輸出結果如下:

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for the base and test modules
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assemble main outputs for all the variants.
assembleAndroidTest - Assembles all the Test applications.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
bundle - Assemble bundles for all the variants.
clean - Deletes the build directory.
cleanBuildCache - Deletes the build cache directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
extractDebugAnnotations - Extracts Android annotations for the debug variant into the archive file
extractReleaseAnnotations - Extracts Android annotations for the release variant into the archive file

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Cleanup tasks
-------------
lintFix - Runs lint on all variants and applies any safe suggestions to the source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'FirstApp'.
components - Displays the components produced by root project 'FirstApp'. [incubating]
dependencies - Displays all dependencies declared in root project 'FirstApp'.
dependencyInsight - Displays the insight into a specific dependency in root project 'FirstApp'.
dependentComponents - Displays the dependent components of components in root project 'FirstApp'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'FirstApp'. [incubating]
projects - Displays the sub-projects of root project 'FirstApp'.
properties - Displays the properties of root project 'FirstApp'.
tasks - Displays the tasks runnable from root project 'FirstApp' (some of the displayed tasks may belong to subprojects).

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
lintVitalRelease - Runs lint on just the fatal issues in the release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

1.2 關于 Build 類型

默認情況下,每個 Android 應用都有兩個版本類型:一個是調試版本,用于調試我們的應用;另一個是發布版本,用于向用戶發布我們的應用。必須先使用證書為從每個版本生成的輸出簽名,然后才能將我們的應用部署到設備。調試版本會使用 SDK 工具提供的調試密鑰自動簽名(此版本不安全,我們不能將其發布到應用市場),而發布版本必須使用我們自己的私鑰進行簽名。

Tips:如果我們要構建發布版應用,還請務必使用適當的簽名密鑰為我們的應用簽名。 不過,如果我們剛剛入門,也可以構建調試版 APK,這樣就可以盡快在模擬器或連接的設備上運行我們的應用。

2. 構建APK

2.1 構建調試版 APK

調試版 APK 使用 SDK 工具提供的調試密鑰進行簽名,并允許通過 adb 進行調試。要構建調試版 APK,請打開命令行,然后轉到項目的根目錄。如需啟動調試版本,請調用 assembleDebug 任務:

gradlew assembleDebug

這將在 project_name/module_name/build/outputs/apk/ 中創建一個名為 module_name-debug.apk 的 APK。 該文件已使用調試密鑰進行簽名并使用 zipalign 對齊,因此我們可以立即將其安裝到設備上。

或者,如需構建 APK 并立即在運行的模擬器或連接的設備上安裝,請改為調用 installDebug:

gradlew installDebug

Tips:上述任務名稱中的“Debug”部分只是構建變體名稱的駝峰式大小寫版本,因此可以替換為我們想組裝或安裝的任何 Build 類型或變體。例如,如果我們有“demo”這個產品變種,則可以使用 assembleDemoDebug 任務來構建調試版本。

2.2 構建發布版 APK

當我們準備好發布和分發我們的應用時,必須構建一個使用我們的私鑰進行簽名的發布版 APK。發布版 APK 和調試版 APK 的不同之處在于私鑰簽名,關于應用簽名部分將在后面介紹。

3. 構建 app bundle

Android App Bundle 包含應用的所有經過編譯的代碼和資源,但 APK 的生成和簽名將轉到 Google Play 上來完成。與 APK 不同的是,我們不能直接將 app bundle 部署到設備上。

如需構建 app bundle,最簡單的方法是使用 Android Studio。不過,如果需要從命令行構建 app bundle,我們可以使用 Gradlebundletool 來執行這項操作。

3.1 Gradle 構建 app bundle

如果我們更喜歡從命令行生成 app bundle,請在應用的基礎模塊上運行 bundleVariant Gradle 任務。 例如,以下命令會為基礎模塊的調試版本構建 app bundle:

./gradlew :base:bundleDebug

如果我們要構建已簽名的 bundle 以上傳到 Play 管理中心,則需要先使用應用的簽名信息來配置基礎模塊的 build.gradle 文件。如何配置 Gradle 來為我們的應用簽名將在后面介紹。當我們配置好 build.gradle 之后,我們就可以構建應用的發布版本,Gradle 會自動生成 app bundle,并使用我們在 build.gradle 文件中提供的簽名信息為其簽名。

3.2 bundletool 構建 app bundle

bundletool 是一個命令行工具,Android Studio、Android Gradle 插件和 Google Play 使用這項工具將應用的經過編譯的代碼和資源轉換為 app bundle,并根據這些 bundle 生成可部署的 APK。

bundletool 要求關于應用項目的某些信息(如應用的清單和資源)采用 Google 的協議緩沖區格式(也稱為“protobuf”),并以 *.pb 作為文件擴展名。Protobuf 提供了一種不依賴于語言和平臺且可擴展的機制,用于對結構化數據進行序列化。

3.2.1 下載 AAPT2

我們可以使用 Google Maven 代碼庫中的最新版 AAPT2protobuf 格式生成應用的清單文件和資源表。

Tips:請勿使用 Android 構建工具包中包含的 AAPT2 版本,因為它不支持 bundletool。

要從 Google 的 Maven 代碼庫下載 AAPT2,請按以下步驟操作:

  1. 在代碼庫索引中依次轉到 com.android.tools.build > aapt2;

  2. 復制最新版 AAPT2 的名稱;

  3. 將復制的版本名稱插入以下網址并指定目標操作系統:https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/aapt2-version/aapt2-aapt2-version-[windows|linux|osx].jar;
    例如,要下載適用于 Windows 的版本 3.2.0-alpha18-4804415,我們應使用:https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/3.2.0-alpha18-4804415/aapt2-3.2.0-alpha18-4804415-windows.jar;

  4. 在瀏覽器中導航到該網址,系統應該會隨即開始下載 AAPT2;

  5. 解壓縮剛剛下載的 JAR 文件。

3.2.2 編譯并鏈接應用的資源

我們可以通過以下命令,使用 AAPT2 編譯應用的資源:

aapt2 compile \
project_root/module_root/src/main/res/drawable/Image1.png \
project_root/module_root/src/main/res/drawable/Image2.png \
-o compiled_resources/

Tips:雖然我們可以使用 --dir 標記將資源目錄傳遞給 AAPT2,但這樣做會重新編譯目錄中的所有文件,無論我們實際更改了多少個文件。

在鏈接階段(在此階段,AAPT2 會將各種編譯后的資源鏈接到一個 APK 中),通過添加 --proto-format 標記,指示 AAPT2 將應用的清單和編譯后的資源轉換為 protobuf 格式,如下所示:

aapt2 link --proto-format -o output.apk \
-I android_sdk/platforms/android_version/android.jar \
--manifest project_root/module_root/src/main/AndroidManifest.xml \
-R compiled_resources/*.flat \
--auto-add-overlay

Tips:此外,當使用 -R 標記指定已編譯的資源時,我們可以指定一個包含每個已編譯資源的絕對路徑(各路徑之間用一個空格分隔)的文本文件。然后,我們可以將該文本文件傳遞給 AAPT2,如下所示:aapt2 link … -R @compiled_resources.txt。

接下來,我們可以從輸出 APK 提取內容,如應用的 AndroidManifest.xml、resources.pb 及其他資源文件(這些文件現在采用 protobuf 格式)。在準備 bundletool 構建 app bundle 所需的輸入時,我們需要用到這些文件。

3.2.3 打包預編譯的代碼和資源

在使用 bundletool 為我們的應用生成 app bundle 之前,我們必須先提供 ZIP 文件,每個 ZIP 文件包含給定應用模塊的經過編譯的代碼和資源。每個模塊的 ZIP 文件的內容和組織方式都與 Android App Bundle 格式非常類似。 例如,我們應該為應用的基礎模塊創建一個 base.zip 文件,并按如下方式組織其內容:

文件或目錄 說明
manifest/AndroidManifest.xml 模塊的清單,采用 protobuf 格式。
dex/… 此目錄包含應用的一個或多個經過編譯的 DEX 文件。這些文件應按如下方式命名:classes.dex、classes2.dex、classes3.dex,依此類推。
res/… 包含模塊的資源,這些資源采用 protobuf 格式,適用于所有設備配置。子目錄和文件的組織方式應與典型的 APK 類似。
root/…、assets/… 和 lib/… 這些目錄與關于 Android App Bundle 格式的目錄完全相同。
resources.pb 應用的資源表,采用 protobuf 格式。

準備好每個應用模塊的 ZIP 文件后,我們可以將其傳遞給 bundletool 來構建 app bundle。

3.2.4 構建 app bundle

要構建 app bundle,請使用 bundletool build-bundle 命令,如下所示:

bundletool build-bundle --modules=base.zip --output=mybundle.aab

下表對用于 build-bundle 命令的標記進行了更詳細的說明:

標記 說明
–modules=path-to-base.zip, path-to-module2.zip,path-to-module3.zip 指定 bundletool 構建 app bundle 時應使用的模塊 ZIP 文件的列表。
–output=path-to-output.aab 指定輸出 *.aab 文件的路徑和文件名。
–config=path-to-BundleConfig.json 指定可用于自定義構建流程的可選配置文件的路徑。
–metadata-file=target-bundle-path:local-file-path 指示 bundletool 將可選的元數據文件打包到 app bundle 中。

3.2.5 自定義 APK 生成

app bundle 包含一個 BundleConfig.pb 文件,該文件提供應用商店(如 Google Play)在根據 bundle 生成 APK 時所需的元數據。 雖然 bundletool 會為我們創建此文件,但我們可以在 BundleConfig.json 文件中配置元數據的某些方面,并將其傳遞給 bundletool build-bundle 命令。bundletool 隨后會轉換此文件并將其與每個 app bundle 中包含的 protobuf 版本進行合并。

例如,我們可以控制要啟用或停用哪些類別的配置 APK。以下 BundleConfig.json 文件示例會停用分別以不同語言為目標的配置 APK(即,各個語言的資源分別包含在各自的基礎功能 APK 或動態功能 APK 中):

{
  "optimizations": {
    "splitsConfig": {
      "splitDimension": [{
        "value": "LANGUAGE",
        "negate": true
      }]
    }
  }
}

在 BundleConfig.json 文件中,我們還可以指定在使用 glob 模式打包 APK 時要讓哪些類型的文件保持未壓縮狀態,如下所示:

{
  "compression": {
    "uncompressedGlob": ["res/raw/**", "assets/**.uncompressed"]
  }
}

4. 應用簽名

不使用 Android Studio 也可以為我們的應用簽名。我們可以從命令行為我們的應用簽名(對于 APK,使用 apksigner;對于 app bundle,使用 jarsigner),或在構建期間配置 Gradle 來為我們的應用簽名。無論使用哪種方式,我們都需要先使用 keytool 生成一個私鑰,如下所示:

keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

上面的示例會提示我們輸入密鑰庫和密鑰的密碼,并提示我們在 Distinguished Name 字段中為我們的密鑰輸入相應的名稱。隨后,它會生成一個名為 my-release-key.jks 的密鑰庫文件,并將其保存在當前目錄中。該密鑰庫包含一個有效期為 10000 天的密鑰。

現在,我們可以手動為我們的 APK 或 app bundle 簽名,也可以在構建過程中配置 Gradle 來為我們的應用簽名,

4.1 使用命令行為應用簽名

如果要從命令行為 app bundle 簽名,我們可以使用 jarsigner。 如果要為 APK 簽名,則需要使用 zipalign 和 apksigner。

  1. 打開命令行(在 Android Studio 中,依次選擇 View > Tool Windows > Terminal),然后轉到未簽名的 APK 所在的目錄。

  2. 使用 zipalign 對齊未簽名的 APK:

zipalign -v -p 4 my-app-unsigned.apk my-app-unsigned-aligned.apk

zipalign 可以確保所有未壓縮數據的開頭均相對于文件開頭執行特定的字節對齊,從而減少應用占用的 RAM 量。

  1. 通過 apksigner 使用我們的私鑰為 APK 簽名:
apksigner sign --ks my-release-key.jks --out my-app-release.apk my-app-unsigned-aligned.apk

在本例中,在使用存儲在單個密鑰庫文件 my-release-key.jks 中的私鑰和證書為 APK 簽名后,將以 my-app-release.apk 的形式輸出已簽名的 APK。

  1. 驗證我們的 APK 是否已簽名:
apksigner verify my-app-release.apk

4.2 配置 Gradle 為應用簽名

打開模塊級 build.gradle 文件,并添加包含 storeFile、storePassword、keyAlias 和 keyPassword 條目的 signingConfigs {} 代碼塊,然后將該對象傳遞給我們的版本類型中的 signingConfig 屬性。例如:

android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            // You need to specify either an absolute path or include the
            // keystore file in the same directory as the build.gradle file.
            storeFile file("my-release-key.jks")
            storePassword "password"
            keyAlias "my-alias"
            keyPassword "password"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            ...
        }
    }
}

現在,當我們通過調用 Gradle 任務來構建我們的應用時,Gradle 會為我們的應用簽名(并運行 zipalign)。此外,因為我們已使用簽名密鑰配置了發布版本,所以該版本類型可以執行“安裝”任務。因此,我們可以使用 installRelease 任務在模擬器或設備上構建、對齊、簽署和安裝發布版 APK。

5. 小結

本節課程我們主要學習了如何在命令行中構建我們的應用。本節課程的重點如下:

  • 了解命令行構建應用的方法;
  • 掌握命令行為應用簽名的方法。