【譯文】Android Gradle 教程:入門


什么是Gradle?

Gradle 是一個開源的構建自動化系統。它擁有基於 Groovy 的 DSL 的便利以及 Ant 和 Maven 的優勢。
使用 Gradle,您可以輕松地操縱構建過程及其邏輯,以創建應用程序的多個版本。與單獨使用 Ant 或 Maven 相比,它更易於使用,更加簡潔和靈活。 

入門

新建一個 Android project,將以該項目進行講解。

在開始處理項目之前,讓我們在 Android Studio 的 "project" 選項中查看其結構:

注意帶有綠色 Gradle 圖標和擴展名 .gradle 的文件。這些文件由Android Studio在項目創建過程中自動生成。他們負責處理項目的構建。它們包含有關項目結構,庫依賴項,庫版本以及在構建過程中將獲得的應用程序版本的必要信息。 

Project 層的 build.gradle

在項目的根目錄中找到 build.gradle 文件。它稱為頂級(項目級別)build.gradle 文件。它包含適用於項目所有模塊的設置。

// 1
buildscript {
    // 2
    repositories {
        google()
        jcenter()
    }
    // 3
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.51'
    }
}

// 4
allprojects {
    repositories {
        google()
        jcenter()
    }
}

這是逐步進行的操作:

  • buildscript 塊中,定義執行項目構建所需的設置。

  • repositories 塊中,添加 Gradle 應搜索使用的庫的存儲庫名稱。

  • dependencies 塊包含必要的插件依賴性,在這種情況下為 Gradle 和 Kotlin 插件。不要將模塊依賴項放在此塊中。

  • allprojects 塊的結構類似於該 buildscript 塊,但是在這里您為所有模塊定義存儲庫,而不是為 Gradle 本身定義存儲庫。通常,您不會為定義該 dependencies 部分 allprojects。每個模塊的依賴關系都不同,並且應位於模塊級 build.gradle 中。

Moudle 層的 build.gradle

現在轉到應用程序模塊目錄中的build.gradle文件。它包含依賴項(模塊所依賴的庫)以及構建過程的說明。每個模塊定義其自己的build.gradle文件。

// 1
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

// 2
android {
    // 3
    compileSdkVersion 27
    // 4
    buildToolsVersion "26.0.2"
    // 5
    defaultConfig {
        // 6
        applicationId "com.raywenderlich.socializify"
        // 7
        minSdkVersion 21
        // 8
        targetSdkVersion 27
        // 9
        versionCode 1
        // 10
        versionName "1.0"
    }
}

// 11
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.1.51'
    implementation 'com.android.support:appcompat-v7:27.0.1'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

上面的代碼執行以下操作:

  1. 指定構建模塊所需的插件列表。該 com.android.application 插件對於設置構建過程的 Android 特定設置是必需的。com.android.library 如果要創建庫模塊,也可以在這里使用。在 kotlin-android 和 kotlin-android-extensions 插件允許你使用 kotlin 語言和相關插件到您的模塊中。

  2. 在該 android 塊中,放置模塊的所有具體平台參數的選項。

  3. compileSdkVersion 選項指示您的應用將使用的 API 級別。換句話說,您不能使用 API​​ 中高於此值的功能。在這里,您已設置了使用 Android Oreo API 的值。

  4. buildToolsVersion 選項指示編譯器的版本。從 Gradle 插件 3.0.0 開始,此字段是可選的。如果未指定,則 Android SDK 使用構建工具的最新下載版本。

  5. defaultConfig 塊包含默認情況下將應用於您應用的所有構建版本(例如,調試,發行等)的選項。

  6. applicationId 是你的應用程序的標識。它應該是唯一的,以便在 Google Play 商店中成功發布或更新您的應用。

  7. 為了設置支持的最低API級別,請使用 minSdkVersion。在 API 級別較低的設備上,您的應用將無法在 Google Play 商店中使用。

  8. targetSdkVersion 參數定義了您的應用經過測試的最大 API 級別。也就是說,您確定您的應用程序可以在具有此 SDK 版本的設備上正常運行,並且不需要任何向后兼容行為。最好的方法是使用最新的API徹底測試應用,並保持您的 targetSdkVersion 等於 compileSdkVersion。

  9. versionCode 是應用程序版本的數值。

  10. versionName 是應用程序版本的用戶友好字符串。

  11. dependencies 塊包含此模塊所需的所有依賴關系。

settings.gradle

根目錄中的 settings.gradle 文件。其內容應如下所示:

include ':app'

在此文件中,應按名稱定義項目的所有模塊。在這里,我們只有一個模塊 — app。在大型,多模塊的項目中,此文件會有更長的列表。

Gradle 命令

要執行Gradle命令,您可以同時使用命令行和 Android Studio。最好從命令行開始,以更深入地了解正在發生的事情。那么,如何開始使用 Gradle 命令呢?非常簡單:使用 gradlew。

什么是 gradlew

gradlew 是 Gradle 包裝器。您無需擔心在計算機上安裝 Gradle,包裝程序將為您完成此操作。甚至更多,它使您可以使用不同版本的 Gradle 構建不同的項目。

打開命令行並移至入該項目的根目錄,之后,執行以下命令:

./gradlew tasks

您將看到一個包含所有可用任務的列表:

> Task :tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
...

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

Help tasks
----------
...

Install tasks
-------------
...

Verification tasks
------------------
...
lint - Runs lint on all variants.
...

To see all tasks, run gradlew tasks --all

To get more detail about task, run gradlew help --task <task>

這些命令可以幫助您完成項目初始化,構建,測試和分析等任務。如果您忘記了一個特定的命令,只需執行 ./gradlew tasks 來找到自己需要的任務。

gradlew assemble

現在,再次瀏覽命令列表,並在該部分下找到以 “assemble” 開頭的命令 Build tasks。運行第一個命令:

./gradlew assemble

 

以下是執行此命令的輸出

> Task :app:compileDebugKotlin
Using kotlin incremental compilation

> Task :app:compileReleaseKotlin
Using kotlin incremental compilation


BUILD SUCCESSFUL in 29s
52 actionable tasks: 52 executed

從輸出中,這是顯而易見的是搖籃的編譯應用程序的兩個版本 - debug 和 release。
通過更改到構建輸出目錄來驗證此內容:

cd app/build/outputs/apk/

要查看目錄的內容,請運行以下命令:

ls -R

該 ls 命令顯示當前目錄中的所有文件和目錄。該 -R 參數強制此命令以遞歸方式執行。換句話說,您不僅會看到當前目錄的內容,還會看到子目錄的內容。

您將獲得以下輸出:

debug    release

./debug:
app-debug.apk    output.json

./release:
app-release-unsigned.apk    output.json

如您所見,Gradle 生成了 debug 和 release apk。

管理依賴關系 

現在是時候對應用程序本身進行更改了。

首先,在項目的根目錄中創建一個名為 dependencies.gradle 的文件。您將使用此文件在一處識別所有項目依賴項版本。將以下內容添加到此文件:

ext {
  minSdkVersion = 17
  targetSdkVersion = 27
  compileSdkVersion = 27
  buildToolsVersion = “ 26.0.2” 
  kotlinVersion = “ 1.1.51
  supportVersion
= “ 27.0.1”   picassoVersion = “ 2.5.2” }

打開項目級別的 build.gradle 文件(位於根目錄中的一個,而不是 app 目錄中的一個!),然后在文件頂部添加以下行:

apply from: 'dependencies.gradle'

現在,您可以像下面這樣使用其他項目構建文件中在 dependencies.gradle 文件中指定的屬性:

應用程序模塊級別的 build.gradle

android {
    compileSdkVersion rootProject.compileSdkVersion
    buildToolsVersion rootProject.buildToolsVersion
    defaultConfig {
        applicationId "com.raywenderlich.socializify"
        minSdkVersion rootProject.minSdkVersion
        targetSdkVersion rootProject.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "com.android.support:appcompat-v7:$rootProject.supportVersion"
    implementation "com.android.support:design:$rootProject.supportVersion"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.kotlinVersion"
}

Gradle依賴項配置

implementation 您先前使用關鍵字是依賴項配置,該配置告訴 Gradle 以這種方式添加依賴,其他模塊無法使用它。該選項大大加快了構建時間。

在某些其他情況下,您可能希望項目的其他模塊可以訪問依賴項。在這種情況下,您可以使用 api 關鍵字。

其他選項包括 runtimeOnly 和 compileOnly 配置,它們僅在運行時或編譯時標記依賴項的可用性。

准備發布:使用 Product Flavors and Build Types

您的應用已准備就緒,您正在考慮怎么從項目中獲利的方法:

一種解決方案是擁有多個版本的應用程序:免費和付費版本。幸運的是,gradle 在構建級別支持此功能,使您可以定義不同構建類型的邊界。但是,在開始之前,您需要了解 Gradle 如何允許您使用不同的應用程序版本。

構建類型

默認情況下,有兩種構建類型 debug 和 release。它們之間的唯一區別是 debuggable 參數的值。換句話說,您可以使用調試版本查看日志並調試應用程序,而發布版本則用於將您的應用程序發布到 Google Play 商店。您可以通過在 android 模塊級 build.gradle 文件的塊中添加以下代碼來為構建類型配置屬性:

buildTypes {
    release {

    }
    debug {

    }
}

在 debug 和 release 塊中,您可以指定應用程序的特定於類型的設置。

Build Signing

構建的最重要的配置之一是其簽名。沒有簽名,您將無法發布您的應用程序,因為有必要驗證您是否是特定應用程序的所有者。盡管您無需簽署調試版本(Android Studio會自動進行簽名),但發行版本應由開發人員簽名。

當你的密鑰庫已准備就緒,下面添加的代碼位於 android 塊下,與上述 buildTypes 塊處於 module 層級的的 build.gradle 文件:

signingConfigs {
    release {
        storeFile file("path to your keystore file")
        storePassword "your store password"
        keyAlias "your key alias"
        keyPassword "your key password"
    }
}

在 signingConfigs 塊中,為構建類型指定簽名信息。注意密鑰庫文件路徑。應該相對於模塊目錄進行指定。換句話說,如果您在模塊目錄中創建了密鑰庫文件並將其命名為“ keystore.jks”,則應指定的值將等於文件名。

更新 buildTypes 塊以自動簽署發布版本:

release {
    signingConfig signingConfigs.release
}

注意:與密鑰庫文件相關的兩個重要注意事項:

  1. 將應用發布到Google Play商店后,后續提交必須使用相同的密鑰庫文件和密碼,以確保安全。

  2. 確保不要將密鑰庫密碼提交給版本控制系統,例如GitHub。您可以通過以下方式進行操作:將密碼保存在與中不同的文件中build.gradle(例如keystorePassword.gradle,在Signing目錄中),然后build.gradle通過以下方式從應用程序模塊級別引用該文件:

    apply from: "../Signing/keystorePassword.gradle

然后確保保持 keystorePassword.gradle 版本控制系統忽略它。其他技術包括將密碼保存在 OS 級環境變量中,尤其是在遠程持續集成系統(例如 CircleCI )上。

Build Flavors

為了創建您的應用程序的多個版本,您需要使用 productflavors。Flavors 是一種區分應用程序屬性的方法,無論它是免費/付費的,分階段的/生產的等等。

您將使用不同的應用程序名稱來區分您的應用程序風格。首先,將以下名稱添加為 strings.xml 文件中的字符串:

<string name="app_name_free">Socializify Free</string>
<string name="app_name_paid">Socializify Paid</string>

並刪除現有的:

<string name="app_name">test</string>

現在,原始 app_name 字符串不再可用,請編輯 AndroidManifest.xml 文件,並將在 application 中的 android:label="@string/app_name" 替換為 android:label="${appName}" 。

同時在 modle 層級 build.gradle 文件的 android 塊中添加以下代碼:

// 1
flavorDimensions "appMode"
// 2
productFlavors {
    // 3
    free {
        // 4
        dimension "appMode"
        // 5
        applicationIdSuffix ".free"
        // 6
        manifestPlaceholders = [appName: "@string/app_name_free"]
    }
    paid {
        dimension "appMode"
        applicationIdSuffix ".paid"
        manifestPlaceholders = [appName: "@string/app_name_paid"]
    }
} 
  1. 您需要指定 flavorDimensions 以正確匹配構建類型。在當前示例中,只需要一個維度 - appMode。

  2. 在 productFlavors 指定具體的  flavors 和 具體的設置。在當前示例中,分別是 free 和 paid。

  3. 指定第一個 productFlavors 的名稱為:free。

  4. 必須指定 dimension 參數值。這里 free flavor 屬於 appMode dimension。

  5. 由於您要為免費和付費功能創建單獨的應用程序,因此需要它們具有不同的應用程序標識符。該 applicationIdSuffix 參數定義了會被附加到一個 applicationId 上,從而讓你的應用程序擁有唯一標識符。

  6. manifestPlaceholders 允許你在構建的時候修改 AndroidManifest.xml 中的屬性。在當前示例中,會根據不同的版本來修改應用名稱。

再次 sync project with  Gradle。項目同步后,運行 tasks 命令,並查看哪些內容發生了改變:

./gradlew tasks

 

您將獲得與第一次運行此命令時類似的任務列表:

...
Build tasks
-----------
...
assembleDebug - Assembles all Debug builds.
assembleFree - Assembles all Free builds.
assemblePaid - Assembles all Paid builds.
assembleRelease - Assembles all Release builds.
...

可以發現,任務添加了一些新的選項。現在,每種構建類型和構建 flavors 都有自己單獨的命令。

從上一個 ./gradlew assemble 任務中刪除生成的輸出文件夾,以便您可以在添加 buildTypes 和 productFlavors 之后看到明顯的區別運行命令:

rm -rf app/build/outputs/apk

然后

./gradlew assembleDebug

命令完成后,檢查輸出目錄:

cd app/build/outputs/apk
ls -R

您將獲得如下內容:

free   paid

./free:
debug

./free/debug:
app-free-debug.apk   output.json

./paid:
debug

./paid/debug:
app-paid-debug.apk   output.json 

您應該生成兩個應用 – freeDebug 和 paidDebug

什么是Build Variant

從上面的輸出中,您實際生成的是不同的構建變體,它們是構建類型 (buildType) 和構建風格 (flavors)組合。也就是說,您有四個可能的構建變體– paidDebug,paidRelease,freeDebug 和 freeRelease。

現在您有兩種不同的構建風格,但是,不同的名稱不足以讓您從中獲利。相反,您將根據構建風格 (flavors)配置應用程序的行為!

現在我們在 MainActivity 中定義一個常量:

private static String PAID_FLAVOR = "paid";

在 onCreate 方法中添加如下變量:

   if (BuildConfig.FLAVOR == PAID_FLAVOR) {
            Toast.makeText(this, "3453", Toast.LENGTH_SHORT).show();
   }

如果是付費版本,就會有個 toast 提示。當然,上面只是一個示例,大家后面

創建任務

有時,您需要構建系統執行更復雜的操作或以某種方式自定義構建過程。例如,您可能希望Gradle輸出名稱中包含構建日期的APK文件。一種可能的解決方案是創建自定義 Gradle 任務。

將以下代碼添加到模塊級別的 build.gradle 文件中,與 android block 處於同一級別:

// 1
task addCurrentDate() {
    // 2
    android.applicationVariants.all { variant ->
        // 3
        variant.outputs.all { output ->
            // 4
            def date = new Date().format("dd-MM-yyyy")
            // 5
            def fileName = variant.name + "_" + date + ".apk"
            // 6
            output.outputFileName = fileName
        }
    }
}

下面說下相關邏輯:

  1. 您定義一個 addCurrentDate() 任務。

  2. 您遍歷所有輸出構建變量。

  3. 您遍歷所有 APK 文件。

  4. 您創建一個實例 Date 並設置其格式。

  5. 您創建一個新的文件名,將當前日期附加到初始名稱之后。

  6. 您將新文件名設置為當前的 APK 文件。

現在,您需要在構建過程的特定時刻執行此任務。在 task addCurrentDate() 塊下面添加以下代碼:

gradle.taskGraph.whenReady {
    addCurrentDate
}

whenReady 當前圖形中充滿任務並准備開始執行時,塊中指定的任務將被調用一次。在這里,您指定 addCurrentDate 任務的名稱。

現在,返回命令行,並確保您位於根目錄中。運行以下命令以組裝構建:

./gradlew assemblePaidRelease

任務完成后,轉到輸出目錄,檢查是否正確命名了內部版本:

cd app/build/outputs/apk/paid/release/
ls

您應該得到類似的輸出:

output.json paidRelease_12-29-2019.apk

如果您的任務正確執行,則所有構建都將使用此約定命名。

到此,關於 gradle 的介紹就到這里。當然這也只是入門,后續還有 gradle 插件等需要繼續學習。

 

參考文章

原文:Gradle Tutorial for Android: Getting Started

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM