Định cấu hình xây dựng

Hệ thống xây dựng Android biên soạn tài nguyên và mã nguồn của ứng dụng rồi đóng gói những tệp đó vào APK hoặc Android App Bundle mà bạn có thể thử nghiệm, triển khai, ký và phân phối. Android Studio sử dụng Gradle, một bộ công cụ xây dựng nâng cao, để tự động hoá và quản lý quy trình xây dựng, đồng thời cho phép bạn xác định các cấu hình xây dựng tuỳ chỉnh linh hoạt. Mỗi cấu hình xây dựng có thể xác định một tập hợp mã và tài nguyên riêng, đồng thời sử dụng lại những phần phổ biến cho tất cả các phiên bản của ứng dụng. Trình bổ trợ Android cho Gradle hoạt động với bộ công cụ xây dựng để cung cấp các quy trình và chế độ cài đặt có thể cấu hình dành riêng cho việc tạo và thử nghiệm các ứng dụng Android.

Gradle và trình bổ trợ Android chạy độc lập với Android Studio. Điều này có nghĩa là bạn có thể xây dựng các ứng dụng Android từ trong Android Studio, dòng lệnh trên máy của bạn hoặc trên các máy không cài đặt Android Studio (chẳng hạn như các máy chủ tích hợp liên tục). Nếu không dùng Android Studio, bạn có thể tìm hiểu cách xây dựng và chạy ứng dụng từ dòng lệnh. Kết quả của bản dựng là như nhau cho dù bạn xây dựng một dự án từ dòng lệnh, trên một máy từ xa hay đang sử dụng Android Studio.

Lưu ý: Vì Gradle và trình bổ trợ Android chạy độc lập với Android Studio, nên bạn cần cập nhật riêng các công cụ xây dựng này. Hãy đọc các ghi chú phát hành để tìm hiểu cách cập nhật Gradle và trình bổ trợ Android.

Tính linh hoạt của hệ thống xây dựng Android cho phép bạn thực hiện cấu hình xây dựng tuỳ chỉnh mà không cần sửa đổi các tệp nguồn cốt lõi của ứng dụng. Phần này sẽ giúp bạn hiểu được cách hoạt động của hệ thống xây dựng Android cũng như cách bạn có thể tuỳ chỉnh và tự động hoá nhiều cấu hình xây dựng. Nếu bạn chỉ muốn tìm hiểu thêm về cách triển khai ứng dụng của mình, hãy xem Xây dựng và chạy từ Android Studio. Để bắt đầu tạo các cấu hình xây dựng tuỳ chỉnh ngay lập tức bằng Android Studio, hãy xem Định cấu hình biến thể xây dựng.

Quy trình xây dựng

Quy trình xây dựng liên quan đến nhiều công cụ và quy trình chuyển đổi dự án của bạn thành Gói ứng dụng Android (APK) hoặc Android App Bundle (AAB). Quy trình xây dựng rất linh hoạt, vì vậy, sẽ rất hữu ích nếu bạn biết một số vấn đề đang xảy ra bên trong.

Hình 1. Quy trình xây dựng mô-đun ứng dụng Android thông thường.

Quy trình xây dựng cho một mô-đun ứng dụng Android thông thường, như minh hoạ trong hình 1, tuân theo các bước chung sau:

  1. Trình biên dịch chuyển đổi mã nguồn của bạn thành các tệp DEX (Dalvik Executable) (bao gồm mã byte chạy trên thiết bị Android) và mọi nội dung khác thành các tài nguyên được biên dịch.
  2. Trình đóng gói kết hợp các tệp DEX và tài nguyên được biên dịch vào một APK hoặc AAB, tuỳ thuộc vào mục tiêu bản dựng đã chọn. Trước khi có thể cài đặt ứng dụng của bạn trên thiết bị Android hoặc phân phối ứng dụng đó đến một cửa hàng, chẳng hạn như Google Play, bạn phải ký APK hoặc AAB.
  3. Trình đóng gói ký APK hoặc AAB của bạn bằng cách sử dụng kho khoá gỡ lỗi hoặc phát hành:
    1. Nếu bạn đang tạo một phiên bản gỡ lỗi của ứng dụng, nghĩa là một ứng dụng mà bạn chỉ muốn thử nghiệm và phân tích, thì trình đóng gói sẽ ký ứng dụng của bạn bằng kho khoá gỡ lỗi. Android Studio tự động định cấu hình các dự án mới bằng kho khoá gỡ lỗi.
    2. Nếu bạn đang tạo một phiên bản phát hành của ứng dụng mà bạn dự định phát hành bên ngoài, thì trình đóng gói sẽ ký ứng dụng của bạn bằng kho khoá phát hành mà bạn cần định cấu hình. Để tạo kho khoá phát hành, hãy tìm hiểu thêm về cách ký ứng dụng trong Android Studio.
  4. Trước khi tạo APK cuối cùng, trình đóng gói sử dụng công cụ zipalign để tối ưu hoá ứng dụng của bạn nhằm sử dụng ít bộ nhớ hơn khi chạy trên thiết bị.

Khi kết thúc quy trình xây dựng, bạn sẽ có APK hoặc AAB gỡ lỗi hoặc phát hành của ứng dụng để có thể triển khai, thử nghiệm hoặc phát hành cho người dùng bên ngoài.

Bảng thuật ngữ về bản dựng Android

Gradle và trình bổ trợ Android giúp bạn định cấu hình các khía cạnh sau của bản dựng:

Các loại hình xây dựng
Các loại hình xây dựng xác định một số thuộc tính mà Gradle sử dụng khi xây dựng và đóng gói ứng dụng của bạn và thường được định cấu hình cho các giai đoạn khác nhau trong vòng đời phát triển của bạn. Ví dụ: loại hình xây dựng gỡ lỗi cho phép các tuỳ chọn gỡ lỗi và ký ứng dụng bằng khoá gỡ lỗi, trong khi loại bản phát hành có thể rút gọn, làm rối mã nguồn và ký ứng dụng bằng khoá phát hành để phân phối. Bạn phải xác định ít nhất một loại hình xây dựng để tạo ứng dụng của mình. Theo mặc định, Android Studio sẽ tạo loại bản gỡ lỗi và bản phát hành. Để bắt đầu tuỳ chỉnh các chế độ cài đặt đóng gói cho ứng dụng, hãy tìm hiểu cách Định cấu hình loại hình xây dựng.
Các phiên bản sản phẩm
Các phiên bản sản phẩm đại diện cho nhiều phiên bản của ứng dụng mà bạn có thể phát hành cho người dùng, chẳng hạn như phiên bản miễn phí và phiên bản có tính phí của ứng dụng. Bạn có thể tuỳ chỉnh các phiên bản sản phẩm để sử dụng mã và tài nguyên khác nhau, trong khi chia sẻ và sử dụng lại các phần phổ biến cho tất cả các phiên bản ứng dụng của mình. Các phiên bản sản phẩm là không bắt buộc và bạn phải tự tạo thủ công. Để bắt đầu tạo các phiên bản khác nhau của ứng dụng, hãy tìm hiểu cách Định cấu hình phiên bản sản phẩm.
Các biến thể xây dựng
Biến thể xây dựng là một sản phẩm chéo thuộc loại hình xây dựng và phiên bản sản phẩm, và là cấu hình mà Gradle sử dụng để xây dựng ứng dụng của bạn. Bằng cách sử dụng các biến thể xây dựng, bạn có thể xây dựng phiên bản gỡ lỗi của các phiên bản sản phẩm trong quá trình phát triển hoặc các phiên bản phát hành đã ký của các phiên bản sản phẩm để phân phối. Mặc dù không trực tiếp định cấu hình các biến thể xây dựng, nhưng bạn có thể định cấu hình các loại hình xây dựng và các phiên bản sản phẩm tạo thành những biến thể đó. Việc tạo thêm các loại hình xây dựng hoặc phiên bản sản phẩm cũng tạo ra các biến thể xây dựng bổ sung. Để tìm hiểu cách tạo và quản lý các biến thể xây dựng, hãy tham khảo phần tổng quan về Định cấu hình các biến thể xây dựng.
Các mục nhập tệp kê khai
Bạn có thể chỉ định giá trị cho một số thuộc tính của tệp kê khai trong cấu hình biến thể xây dựng. Các giá trị xây dựng này sẽ ghi đè các giá trị hiện có trong tệp kê khai. Tính năng này rất hữu ích nếu bạn muốn tạo nhiều biến thể của ứng dụng bằng một tên ứng dụng, phiên bản SDK tối thiểu hoặc phiên bản SDK mục tiêu khác. Khi có nhiều tệp kê khai, Gradle sẽ hợp nhất các chế độ cài đặt tệp kê khai.
Phần phụ thuộc
Hệ thống xây dựng quản lý các phần phụ thuộc của dự án từ hệ thống tệp cục bộ và từ kho lưu trữ từ xa. Nhờ đó, bạn không phải tìm kiếm, tải xuống và sao chép thủ công các gói nhị phân về các phần phụ thuộc vào thư mục dự án của bạn. Để tìm hiểu thêm, hãy tham khảo phần Thêm phần phụ thuộc của bản dựng.
Hệ thống xây dựng cho phép bạn chỉ định các chế độ cài đặt ký trong cấu hình xây dựng và hệ thống có thể tự động ký ứng dụng của bạn trong quá trình tạo. Hệ thống xây dựng ký phiên bản gỡ lỗi bằng một khoá và chứng chỉ mặc định sử dụng thông tin đăng nhập đã biết để tránh hiển thị lời nhắc nhập mật khẩu tại thời điểm xây dựng. Hệ thống xây dựng không ký phiên bản phát hành trừ khi bạn xác định rõ cấu hình ký tên cho bản dựng này. Nếu không có khoá phát hành, bạn có thể tạo một khoá như mô tả trong phần Ký ứng dụng.
Rút gọn mã và tài nguyên
Hệ thống xây dựng cho phép bạn chỉ định cho mỗi biến thể xây dựng một tệp quy tắc ProGuard khác nhau. Khi bạn xây dựng ứng dụng, hệ thống xây dựng sẽ áp dụng một bộ quy tắc thích hợp để rút gọn mã và tài nguyên của bạn bằng các công cụ rút gọn tích hợp sẵn, chẳng hạn như R8.
Hỗ trợ nhiều APK
Hệ thống xây dựng cho phép bạn tự động xây dựng nhiều APK khác nhau, trong đó mỗi APK chỉ chứa mã và tài nguyên cần thiết cho một mật độ màn hình hoặc Giao diện nhị phân của ứng dụng (ABI) cụ thể. Để biết thêm thông tin, hãy xem Tạo nhiều APK. Xin lưu ý rằng việc phát hành AAB đơn lẻ là phương pháp được đề xuất vì phương pháp này cung cấp chức năng phân tách theo ngôn ngữ cùng với mật độ màn hình và ABI, đồng thời giảm sự phức tạp khi phải tải nhiều cấu phần phần mềm lên Google Play.

Tệp cấu hình xây dựng

Việc tạo cấu hình xây dựng tuỳ chỉnh yêu cầu bạn phải thay đổi một hoặc nhiều tệp cấu hình xây dựng hoặc tệp build.gradle. Các tệp văn bản thuần tuý này sử dụng Ngôn ngữ dành riêng cho miền (DSL) để mô tả và điều khiển logic xây dựng bằng Groovy, một ngôn ngữ động của Máy ảo Java (VM). Bạn không cần phải biết Groovy để bắt đầu định cấu hình bản dựng của mình vì trình bổ trợ Android cho Gradle sẽ giới thiệu hầu hết các phần tử DSL mà bạn cần. Để tìm hiểu thêm về DSL của trình bổ trợ Android, hãy đọc tài liệu tham khảo về DSL.

Khi bắt đầu một dự án mới, Android Studio sẽ tự động tạo một số tệp trong số này cho bạn, như minh hoạ trong hình 2 và điền các tệp đó dựa trên giá trị mặc định thích hợp.

Hình 2. Cấu trúc dự án mặc định của mô-đun ứng dụng Android.

Có một số tệp cấu hình xây dựng Gradle là một phần của cấu trúc dự án chuẩn cho một ứng dụng Android. Trước khi có thể bắt đầu định cấu hình bản dựng, bạn cần hiểu được phạm vi và mục đích của từng tệp trong đó cũng như các phần tử DSL cơ bản mà chúng cần xác định.

Tệp cài đặt Gradle

Tệp settings.gradle nằm trong thư mục dự án gốc xác định các chế độ cài đặt kho lưu trữ ở cấp dự án và cho Gradle biết những mô-đun mà Gradle nên bao gồm khi xây dựng ứng dụng của bạn. Đối với hầu hết các dự án, theo mặc định, tệp sẽ có dạng như sau:

Groovy

pluginManagement {

    /**
     * The pluginManagement {repositories {...}} block configures the
     * repositories Gradle uses to search or download the Gradle plugins and
     * their transitive dependencies. Gradle pre-configures support for remote
     * repositories such as JCenter, Maven Central, and Ivy. You can also use
     * local repositories or define your own remote repositories. The code below
     * defines the Gradle Plugin Portal, Google's Maven repository,
     * and the Maven Central Repository as the repositories Gradle should use to look for its dependencies.
     */

    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
dependencyResolutionManagement {

    /**
     * The dependencyResolutionManagement { repositories {...}}
     * block is where you configure the repositories and dependencies used by
     * all modules in your project, such as libraries that you are using to
     * create your application. However, you should configure module-specific
     * dependencies in each module-level build.gradle file. For new projects,
     * Android Studio includes Google's Maven repository
     * and the Maven Central Repository by
     * default, but it does not configure any dependencies (unless you select a
     * template that requires some).
     */

    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "My Application"
include ‘:app’

Kotlin

pluginManagement {

    /**
     * The pluginManagement {repositories {...}} block configures the
     * repositories Gradle uses to search or download the Gradle plugins and
     * their transitive dependencies. Gradle pre-configures support for remote
     * repositories such as JCenter, Maven Central, and Ivy. You can also use
     * local repositories or define your own remote repositories. The code below
     * defines the Gradle Plugin Portal, Google's Maven repository,
     * and the Maven Central Repository as the repositories Gradle should use to look for its dependencies.
     */

    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
dependencyResolutionManagement {

    /**
     * The dependencyResolutionManagement { repositories {...}}
     * block is where you configure the repositories and dependencies used by
     * all modules in your project, such as libraries that you are using to
     * create your application. However, you should configure module-specific
     * dependencies in each module-level build.gradle file. For new projects,
     * Android Studio includes Google's Maven repository and the
     * Maven Central Repository by
     * default, but it does not configure any dependencies (unless you select a
     * template that requires some).
     */

    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "My Application"
include(":app")

Các dự án có nhiều mô-đun cần chỉ định từng mô-đun sẽ đi vào bản dựng cuối cùng.

Tệp bản dựng cấp cao nhất

Tệp build.gradle cấp cao nhất nằm trong thư mục gốc của dự án, xác định các phần phụ thuộc áp dụng cho mọi mô-đun trong dự án của bạn. Theo mặc định, tệp bản dựng cấp cao nhất sử dụng khối plugins để xác định các phần phụ thuộc Gradle phổ biến với tất cả các mô-đun trong dự án. Ngoài ra, tệp bản dựng cấp cao nhất còn chứa mã để dọn sạch thư mục bản dựng của bạn. Mã mẫu sau đây mô tả các chế độ cài đặt mặc định và các phần tử DSL mà bạn có thể tìm thấy trong tệp build.gradle cấp cao nhất sau khi tạo dự án mới.

Groovy

plugins {

    /**
     * You should use `apply false` in the top-level build.gradle file
     * to add a Gradle plugin as a build dependency, but not apply it to the
     * current (root) project. You should not use `apply false` in sub-projects.
     * For more information, see
     * Applying external plugins with same version to subprojects.
     */

    id 'com.android.application' version '7.2' apply false
    id 'com.android.library' version '7.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Kotlin

plugins {

    /**
     * You should use `apply false` in the top-level build.gradle file
     * to add a Gradle plugin as a build dependency, but not apply it to the
     * current (root) project. You should not use `apply false` in sub-projects.
     * For more information, see
     * Applying external plugins with same version to subprojects.
     */

    id("com.android.application") version "7.1.0-beta02" apply false
    id("com.android.library") version "7.1.0-beta02" apply false
    id("org.jetbrains.kotlin.android") version "1.5.30" apply false
}

tasks.register("clean", Delete::class) {
    delete(rootProject.buildDir)
}

Định cấu hình các thuộc tính trên toàn dự án

Đối với các dự án Android chứa nhiều mô-đun, bạn có thể xác định một số thuộc tính nhất định ở cấp dự án và chia sẻ các thuộc tính đó trên tất cả các mô-đun. Bạn có thể thực hiện việc này bằng cách thêm các thuộc tính bổ sung vào khối ext trong tệp build.gradle cấp cao nhất.

Groovy

// This block encapsulates custom properties and makes them available to all
// modules in the project. The following are only a few examples of the types
// of properties you can define.
ext {
    sdkVersion = 28
    // You can also create properties to specify versions for dependencies.
    // Having consistent versions between modules can avoid conflicts with behavior.
    supportLibVersion = "28.0.0"
    ...
}
...

Kotlin

// This block encapsulates custom properties and makes them available to all
// modules in the project. The following are only a few examples of the types
// of properties you can define.
ext {
  extra["compileSdkVersion"] = 28
  // You can also create properties to specify versions for dependencies.
  // Having consistent versions between modules can avoid conflicts with behavior.
  extra["supportLibVersion"] = "28.0.0"
...
}
...

Để truy cập vào các thuộc tính này từ một mô-đun trong cùng một dự án, hãy sử dụng cú pháp sau đây trong tệp build.gradle của mô-đun (bạn có thể tìm hiểu thêm về tệp này trong phần dưới đây).

Groovy

android {
    // Use the following syntax to access properties you defined at the project level:
    // rootProject.ext.property_name
    compileSdkVersion rootProject.ext.compileSdkVersion
    ...
}
...
dependencies {
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    ...
}

Kotlin

android {
    // Use the following syntax to access properties you defined at the project level:
    // rootProject.extra["property_name"]
    compileSdk = rootProject.extra["sdkVersion"]

    // Alternatively, you can access properties using a type safe delegate:
    val sdkVersion: Int by rootProject.extra
    ...
    compileSdk = sdkVersion
}
...
dependencies {
    implementation("com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}")
    ...
}

Lưu ý: Mặc dù Gradle cho phép bạn xác định các thuộc tính trên toàn dự án ở cấp mô-đun, nhưng bạn nên tránh làm như vậy vì điều này khiến các mô-đun có chung các thuộc tính đó bị ghép nối. Ghép nối mô-đun làm cho quá trình xuất mô-đun sau này dưới dạng dự án độc lập và ngăn Gradle sử dụng phương thức thực thi dự án song song để tăng tốc độ hoạt động mô-đun bản dựng trở nên khó khăn.

Tệp bản dựng cấp mô-đun

Tệp build.gradle cấp mô-đun nằm trong từng thư mục project/module/, cho phép bạn định cấu hình các chế độ cài đặt bản dựng cho mô-đun cụ thể chứa thư mục đó. Việc định cấu hình các chế độ cài đặt bản dựng này cho phép bạn cung cấp các tuỳ chọn đóng gói tuỳ chỉnh, chẳng hạn như các loại hình xây dựng bổ sung và phiên bản sản phẩm, cũng như ghi đè các chế độ cài đặt trong tệp kê khai main/ hoặc tệp build.gradle cấp cao nhất.

Tệp build.gradle của mô-đun ứng dụng Android mẫu này nêu ra một số phần tử và chế độ cài đặt DSL cơ bản mà bạn nên biết.

Groovy

/**
 * The first line in the build configuration applies the Android plugin for
 * Gradle to this build and makes the android block available to specify
 * Android-specific build options.
 */

plugins {
  id 'com.android.application'
}

/**
 * The android block is where you configure all your Android-specific
 * build options.
 */

android {

    /**
     * compileSdkVersion specifies the Android API level Gradle should use to
     * compile your app. This means your app can use the API features included in
     * this API level and lower.
     */

    compileSdkVersion 28

    /**
     * buildToolsVersion specifies the version of the SDK build tools, command-line
     * utilities, and compiler that Gradle should use to build your app. You need to
     * download the build tools using the SDK Manager.
     *
     * This property is optional because the plugin uses a recommended version of
     * the build tools by default.
     */

    buildToolsVersion "30.0.2"

    /**
     * The defaultConfig block encapsulates default settings and entries for all
     * build variants, and can override some attributes in main/AndroidManifest.xml
     * dynamically from the build system. You can configure product flavors to override
     * these values for different versions of your app.
     */

    defaultConfig {

        /**
         * applicationId uniquely identifies the package for publishing.
         * However, your source code should still reference the package name
         * defined by the namespace property (for simplicity, keep the
         * applicationId and namespace the same).
         */

        applicationId 'com.example.myapp'

        // Defines the minimum API level required to run the app.
        minSdkVersion 15

        // Specifies the API level used to test the app.
        targetSdkVersion 28

        // Defines the version number of your app.
        versionCode 1

        // Defines a user-friendly version name for your app.
        versionName "1.0"
    }

    /**
     * The buildTypes block is where you can configure multiple build types.
     * By default, the build system defines two build types: debug and release. The
     * debug build type is not explicitly shown in the default build configuration,
     * but it includes debugging tools and is signed with the debug key. The release
     * build type applies Proguard settings and is not signed by default.
     */

    buildTypes {

        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default Proguard rules file.
         */

        release {
              minifyEnabled true // Enables code shrinking for the release build type.
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    /**
     * The productFlavors block is where you can configure multiple product flavors.
     * This allows you to create different versions of your app that can
     * override the defaultConfig block with their own settings. Product flavors
     * are optional, and the build system does not create them by default.
     *
     * This example creates a free and paid product flavor. Each product flavor
     * then specifies its own application ID, so that they can exist on the Google
     * Play Store, or an Android device, simultaneously.
     *
     * If you declare product flavors, you must also declare flavor dimensions
     * and assign each flavor to a flavor dimension.
     */

    flavorDimensions "tier"
    productFlavors {
        free {
            dimension "tier"
            applicationId 'com.example.myapp.free'
        }

        paid {
            dimension "tier"
            applicationId 'com.example.myapp.paid'
        }
    }
}

/**
 * The dependencies block in the module-level build configuration file
 * specifies dependencies required to build only the module itself.
 * To learn more, go to Add build dependencies.
 */

dependencies {
    implementation project(":lib")
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

Kotlin

/**
 * The first section in the build configuration applies the Android plugin for
 * Gradle to this build and makes the android block available to specify
 * Android-specific build options.
 */

plugins {
    id("com.android.application")
}

/**
 * The android block is where you configure all your Android-specific
 * build options.
 */

android {

    /**
     * compileSdkVersion specifies the Android API level Gradle should use to
     * compile your app. This means your app can use the API features included in
     * this API level and lower.
     */

    compileSdk = 28

    /**
     * buildToolsVersion specifies the version of the SDK build tools, command-line
     * utilities, and compiler that Gradle should use to build your app. You need to
     * download the build tools using the SDK Manager.
     *
     * This property is optional because the plugin uses a recommended version of
     * the build tools by default.
     */

    buildToolsVersion = "30.0.2"

    /**
     * The defaultConfig block encapsulates default settings and entries for all
     * build variants, and can override some attributes in main/AndroidManifest.xml
     * dynamically from the build system. You can configure product flavors to override
     * these values for different versions of your app.
     */

    defaultConfig {

        /**
         * applicationId uniquely identifies the package for publishing.
         * However, your source code should still reference the package name
         * defined by the namespace property (for simplicity, keep the
         * applicationId and namespace the same).
         */

        applicationId = "com.example.myapp"

        // Defines the minimum API level required to run the app.
        minSdk = 15

        // Specifies the API level used to test the app.
        targetSdk = 28

        // Defines the version number of your app.
        versionCode = 1

        // Defines a user-friendly version name for your app.
        versionName = "1.0"
    }

    /**
     * The buildTypes block is where you can configure multiple build types.
     * By default, the build system defines two build types: debug and release. The
     * debug build type is not explicitly shown in the default build configuration,
     * but it includes debugging tools and is signed with the debug key. The release
     * build type applies Proguard settings and is not signed by default.
     */

    buildTypes {

        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default Proguard rules file.
         */

        getByName("release") {
            isMinifyEnabled = true // Enables code shrinking for the release build type.
            proguardFiles(
                getDefaultProguardFile("proguard-android.txt"),
                "proguard-rules.pro"
            )
        }
    }

    /**
     * The productFlavors block is where you can configure multiple product flavors.
     * This allows you to create different versions of your app that can
     * override the defaultConfig block with their own settings. Product flavors
     * are optional, and the build system does not create them by default.
     *
     * This example creates a free and paid product flavor. Each product flavor
     * then specifies its own application ID, so that they can exist on the Google
     * Play Store, or an Android device, simultaneously.
     *
     * If you declare product flavors, you must also declare flavor dimensions
     * and assign each flavor to a flavor dimension.
     */

    flavorDimensions = "tier"
    productFlavors {
        create("free") {
            dimension = "tier"
            applicationId = "com.example.myapp.free"
        }

        create("paid") {
            dimension = "tier"
            applicationId = "com.example.myapp.paid"
        }
    }
}

/**
 * The dependencies block in the module-level build configuration file
 * specifies dependencies required to build only the module itself.
 * To learn more, go to Add build dependencies.
 */

dependencies {
    implementation(project(":lib"))
    implementation("com.android.support:appcompat-v7:28.0.0")
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
}

Tệp thuộc tính Gradle

Gradle cũng bao gồm 2 tệp thuộc tính nằm trong thư mục của dự án gốc mà bạn có thể dùng để chỉ định các chế độ cài đặt cho chính bộ công cụ xây dựng Gradle:

gradle.properties
Đây là nơi bạn có thể định cấu hình các chế độ cài đặt Gradle trên toàn dự án, chẳng hạn như kích thước tối đa của vùng nhớ khối xếp trong trình nền của Gradle. Để biết thêm thông tin, hãy xem Môi trường tạo bản dựng.
local.properties
Định cấu hình các thuộc tính môi trường cục bộ của hệ thống xây dựng, bao gồm các thuộc tính sau:
  • ndk.dir – Đường dẫn đến NDK. Thuộc tính này không được dùng nữa. Mọi phiên bản NDK đã tải xuống sẽ được cài đặt trong thư mục ndk trong thư mục SDK Android.
  • sdk.dir – Đường dẫn đến SDK.
  • cmake.dir – Đường dẫn đến CMake.
  • ndk.symlinkdir – trong Android Studio 3.5 trở lên, tạo ra một mối liên kết tượng trưng với NDK có thể ngắn hơn đường dẫn NDK đã cài đặt.

Liên kết lại NDK thành một đường dẫn ngắn hơn (chỉ dành cho Windows)

Vấn đề phổ biến nhất với các đường dẫn dài của Windows là các công cụ (chẳng hạn như ld.exe) trong thư mục NDK đã cài đặt dẫn đến các đường dẫn rất sâu, nhưng các công cụ này không hỗ trợ tốt các đường dẫn dài.

Trong local.properties, bạn có thể đặt thuộc tính ndk.symlinkdir để yêu cầu trình bổ trợ Gradle tạo một đường liên kết tượng trưng cho NDK. Đường dẫn của đường liên kết tượng trưng đó có thể ngắn hơn thư mục NDK hiện có. Ví dụ: ndk.symlinkdir = C:\ sẽ dẫn đến đường liên kết tượng trưng sau: C:\ndk\19.0.5232133

Đồng bộ hoá dự án với các tệp Gradle

Khi bạn thay đổi các tệp cấu hình xây dựng trong dự án, Android Studio sẽ yêu cầu bạn đồng bộ hoá các tệp dự án để tệp có thể nhập các thay đổi về cấu hình xây dựng và chạy một số tuỳ chọn kiểm tra để đảm bảo cấu hình của bạn sẽ không tạo ra lỗi bản dựng.

Để đồng bộ hoá các tệp dự án của bạn, hãy nhấp vào Sync Now (Đồng bộ hoá ngay) trong thanh thông báo xuất hiện khi bạn thực hiện thay đổi, như minh hoạ trong hình 3 hoặc nhấp vào biểu tượng Sync Project (Đồng bộ hoá dự án) trên thanh trình đơn. Nếu Android Studio phát hiện bất kỳ lỗi nào với cấu hình của bạn, chẳng hạn như mã nguồn của bạn sẽ sử dụng các tính năng API chỉ có ở cấp API cao hơn compileSdkVersion của bạn, thì cửa sổ Message (Thông báo) sẽ xuất hiện để mô tả vấn đề.

Hình 3. Đồng bộ hoá dự án với các tệp cấu hình xây dựng trong Android Studio.

Nhóm tài nguyên

Android Studio sẽ nhóm mã nguồn và các tài nguyên cho từng mô-đun vào các nhóm tài nguyên. Nhóm tài nguyên main/ của một mô-đun bao gồm mã và tài nguyên mà tất cả các biến thể xây dựng của nó sử dụng. Bạn không bắt buộc phải có các thư mục nhóm tài nguyên bổ sung, và Android Studio sẽ không tự động tạo các thư mục này cho bạn khi bạn định cấu hình các biến thể xây dựng mới. Tuy nhiên, việc tạo nhóm tài nguyên tương tự như main/, giúp sắp xếp các tệp và tài nguyên mà Gradle sẽ chỉ sử dụng khi tạo một số phiên bản nhất định của ứng dụng:

src/main/
Nhóm tài nguyên này bao gồm mã và các tài nguyên chung cho tất cả các biến thể xây dựng.
src/buildType/
Tạo nhóm tài nguyên này để chỉ bao gồm mã và tài nguyên cho một loại hình xây dựng cụ thể.
src/productFlavor/
Tạo nhóm tài nguyên này để chỉ bao gồm mã và các tài nguyên cho một phiên bản sản phẩm cụ thể.

Lưu ý: Nếu định cấu hình bản dựng để kết hợp nhiều phiên bản sản phẩm, bạn có thể tạo thư mục nhóm tài nguyên cho mỗi tổ hợp trong số phiên bản sản phẩm giữa các nhóm phiên bản: src/productFlavor1ProductFlavor2/

src/productFlavorBuildType/
Tạo nhóm tài nguyên này để chỉ bao gồm mã và tài nguyên cho một biến thể xây dựng cụ thể.

Ví dụ: để tạo phiên bản "fullDebug" của ứng dụng, hệ thống xây dựng sẽ hợp nhất mã, chế độ cài đặt và tài nguyên từ các nhóm tài nguyên sau:

  • src/fullDebug/ (nhóm tài nguyên biến thể xây dựng)
  • src/debug/ (nhóm tài nguyên của loại hình xây dựng)
  • src/full/ (nhóm tài nguyên của phiên bản sản phẩm)
  • src/main/ (nhóm tài nguyên chính)

Lưu ý: Khi tạo một tệp hoặc thư mục mới trong Android Studio, bạn có thể sử dụng các lựa chọn trong trình đơn File > New (Tệp > Mới) để tạo tệp hoặc thư mục cho một nhóm tài nguyên. Các nhóm tài nguyên mà bạn có thể chọn dựa trên cấu hình xây dựng của bạn và Android Studio sẽ tự động tạo các thư mục bắt buộc nếu chưa có thư mục.

Nếu các nhóm tài nguyên khác nhau chứa các phiên bản khác nhau của cùng một tệp, thì Gradle sẽ sử dụng thứ tự ưu tiên sau khi quyết định tệp sẽ sử dụng (nhóm tài nguyên ở bên trái ghi đè các tệp và chế độ cài đặt của nhóm tài nguyên ở bên phải):

biến thể bản dựng > loại hình xây dựng > phiên bản sản phẩm > nhóm tài nguyên chính > phần phụ thuộc thư viện

Điều này cho phép Gradle sử dụng những tệp dành riêng cho biến thể xây dựng mà bạn đang cố gắng xây dựng trong khi sử dụng lại các hoạt động, logic ứng dụng và các tài nguyên phổ biến với các phiên bản khác của ứng dụng. Khi hợp nhất nhiều tệp kê khai, Gradle sẽ sử dụng cùng một thứ tự ưu tiên, vì vậy, mỗi biến thể xây dựng có thể xác định các thành phần hoặc quyền khác nhau trong tệp kê khai cuối cùng. Để tìm hiểu thêm về cách tạo nhóm tài nguyên tuỳ chỉnh, hãy chuyển đến phần Create Source Sets for Build Variants. (Tạo nhóm tài nguyên của biến thể xây dựng).