กำหนดค่าตัวแปรของบิวด์

หน้านี้แสดงวิธีกำหนดค่าตัวแปรบิลด์เพื่อ สร้างแอปเวอร์ชันต่างๆ จากโปรเจ็กต์เดียว และวิธี จัดการการกำหนดค่าการขึ้นต่อกันและการลงนามอย่างเหมาะสม

ตัวแปรบิลด์แต่ละรายการแสดงถึงแอปเวอร์ชันต่างๆ ที่คุณสร้างได้ เช่น คุณอาจต้องการสร้างแอปเวอร์ชันหนึ่ง ที่ให้บริการฟรีพร้อมเนื้อหาแบบจำกัด และอีกเวอร์ชันหนึ่งที่ต้องชำระเงิน ซึ่งมีเนื้อหามากกว่า นอกจากนี้ คุณยังสร้างแอปเวอร์ชันต่างๆ ที่กำหนดเป้าหมายเป็นอุปกรณ์ที่แตกต่างกันได้ โดยอิงตามระดับ API หรือความแตกต่างอื่นๆ ของอุปกรณ์

ตัวแปรบิลด์เป็นผลลัพธ์ที่ได้จาก Gradle ซึ่งใช้ชุดกฎที่เฉพาะเจาะจง เพื่อรวมการตั้งค่า โค้ด และทรัพยากรที่กำหนดค่าไว้ใน ประเภทบิลด์และ Product Flavor แม้ว่าคุณจะไม่ได้กำหนดค่าตัวแปรของบิวด์โดยตรง แต่คุณก็กำหนดค่าประเภทบิวด์และรสชาติของผลิตภัณฑ์ที่ประกอบกันเป็นตัวแปรของบิวด์ได้

ตัวอย่างเช่น Product Flavor "demo" อาจระบุฟีเจอร์บางอย่าง และข้อกำหนดของอุปกรณ์ เช่น ซอร์สโค้ด ทรัพยากร และระดับ API ขั้นต่ำ ในขณะที่ประเภทบิลด์ "debug" จะใช้การตั้งค่าบิลด์และ การแพ็กเกจที่แตกต่างกัน เช่น ตัวเลือกการแก้ไขข้อบกพร่องและคีย์การลงนาม ตัวแปรบิลด์ที่รวมทั้ง 2 อย่างนี้คือแอปเวอร์ชัน "demoDebug" ซึ่งมีการ รวมการกำหนดค่าและทรัพยากรที่รวมอยู่ในรสชาติผลิตภัณฑ์ "demo" ประเภทบิลด์ "debug" และชุดแหล่งที่มา main/

กำหนดค่าประเภทบิวด์

คุณสร้างและกำหนดค่าประเภทบิลด์ได้ภายในบล็อก android ของไฟล์ build.gradle.kts ระดับโมดูล เมื่อคุณสร้างโมดูลใหม่ Android Studio จะสร้างประเภทบิลด์ดีบักและรีลีสโดยอัตโนมัติ แม้ว่าประเภทบิลด์สำหรับแก้ไขข้อบกพร่องจะไม่ปรากฏในไฟล์การกำหนดค่าบิลด์ แต่ Android Studio จะกำหนดค่าด้วย debuggable true ซึ่งจะช่วยให้คุณแก้ไขข้อบกพร่องของแอปในอุปกรณ์ Android ที่ปลอดภัยและ กำหนดค่า App Signing ด้วยที่เก็บคีย์การแก้ไขข้อบกพร่องทั่วไป

คุณเพิ่มประเภทบิลด์การแก้ไขข้อบกพร่องลงในการกำหนดค่าได้หากต้องการเพิ่ม หรือเปลี่ยนการตั้งค่าบางอย่าง ตัวอย่างต่อไปนี้ระบุ applicationIdSuffix สำหรับประเภทบิลด์การแก้ไขข้อบกพร่อง และกำหนดค่า ประเภทบิลด์ "staging" ที่เริ่มต้นโดยใช้การตั้งค่าจากประเภทบิลด์การแก้ไขข้อบกพร่อง

Kotlin

android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
        ...
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
        }

        getByName("debug") {
            applicationIdSuffix = ".debug"
            isDebuggable = true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        create("staging") {
            initWith(getByName("debug"))
            manifestPlaceholders["hostName"] = "internal.example.com"
            applicationIdSuffix = ".debugStaging"
        }
    }
}

Groovy

android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
        ...
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        /**
         * The `initWith` property lets you copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        staging {
            initWith debug
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        }
    }
}

หมายเหตุ: เมื่อทำการเปลี่ยนแปลงไฟล์การกำหนดค่าบิลด์ Android Studio จะกำหนดให้คุณซิงค์โปรเจ็กต์กับการกำหนดค่าใหม่ หากต้องการซิงค์โปรเจ็กต์ ให้คลิกซิงค์เลย ในแถบการแจ้งเตือนที่ปรากฏขึ้นเมื่อคุณทำการเปลี่ยนแปลง หรือคลิก ซิงค์โปรเจ็กต์ จากแถบเครื่องมือ หาก Android Studio พบข้อผิดพลาดในการกำหนดค่า หน้าต่างข้อความจะปรากฏขึ้นเพื่ออธิบายปัญหา

ดูข้อมูลเพิ่มเติมเกี่ยวกับพร็อพเพอร์ตี้ทั้งหมดที่คุณกําหนดค่าได้ด้วยประเภทบิลด์ โปรดอ่านข้อมูลอ้างอิง BuildType

กำหนดค่ารสชาติของผลิตภัณฑ์

การสร้างรสชาติของผลิตภัณฑ์คล้ายกับการสร้างประเภทบิลด์ เพิ่มรสชาติของผลิตภัณฑ์ลงในบล็อก productFlavors ในการกำหนดค่าบิลด์และรวมการตั้งค่าที่ต้องการ Product Flavor รองรับพร็อพเพอร์ตี้เดียวกันกับ defaultConfig เนื่องจาก defaultConfig เป็นของคลาส ProductFlavor ซึ่งหมายความว่าคุณสามารถระบุการกำหนดค่าพื้นฐานสำหรับทุกรสชาติในบล็อก defaultConfig และแต่ละรสชาติสามารถเปลี่ยนค่าเริ่มต้นเหล่านี้ได้ เช่น applicationId หากต้องการ ดูข้อมูลเพิ่มเติมเกี่ยวกับรหัสแอปพลิเคชัน โปรดอ่าน ตั้งค่ารหัสแอปพลิเคชัน

หมายเหตุ: คุณยังคงต้องระบุชื่อแพ็กเกจโดยใช้แอตทริบิวต์ package ในไฟล์ Manifest main/ คุณต้องใช้ชื่อแพ็กเกจนั้นในซอร์สโค้ดเพื่ออ้างอิงถึงคลาส R หรือเพื่อแก้ไข การลงทะเบียนกิจกรรมหรือบริการที่เกี่ยวข้องด้วย ซึ่งจะช่วยให้คุณใช้ applicationId เพื่อให้ผลิตภัณฑ์แต่ละรสชาติมีรหัสที่ไม่ซ้ำกันสำหรับ การบรรจุและการจัดจำหน่ายโดยไม่ต้องเปลี่ยนซอร์สโค้ด

รสชาติทั้งหมดต้องอยู่ในมิติข้อมูลรสชาติที่มีชื่อ ซึ่งเป็นกลุ่มของ รสชาติผลิตภัณฑ์ คุณต้องกำหนดรสชาติทั้งหมดให้กับมิติข้อมูลรสชาติ ไม่เช่นนั้นจะได้รับข้อผิดพลาดในการสร้างต่อไปนี้

  Error: All flavors must now belong to a named flavor dimension.
  The flavor 'flavor_name' is not assigned to a flavor dimension.

หากโมดูลที่ระบุมีมิติข้อมูล Flavor เพียงรายการเดียว ปลั๊กอิน Android Gradle จะกำหนด Flavor ทั้งหมดของโมดูลให้กับมิติข้อมูลนั้นโดยอัตโนมัติ

ตัวอย่างโค้ดต่อไปนี้สร้างมิติข้อมูลรสชาติชื่อ "version" และเพิ่มรสชาติผลิตภัณฑ์ "demo" และ "full" โดยรสชาติเหล่านี้จะมี applicationIdSuffix และ versionNameSuffix ของตัวเอง

Kotlin

android {
    ...
    defaultConfig {...}
    buildTypes {
        getByName("debug"){...}
        getByName("release"){...}
    }
    // Specifies one flavor dimension.
    flavorDimensions += "version"
    productFlavors {
        create("demo") {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension = "version"
            applicationIdSuffix = ".demo"
            versionNameSuffix = "-demo"
        }
        create("full") {
            dimension = "version"
            applicationIdSuffix = ".full"
            versionNameSuffix = "-full"
        }
    }
}

Groovy

android {
    ...
    defaultConfig {...}
    buildTypes {
        debug{...}
        release{...}
    }
    // Specifies one flavor dimension.
    flavorDimensions "version"
    productFlavors {
        demo {
            // Assigns this product flavor to the "version" flavor dimension.
            // If you are using only one dimension, this property is optional,
            // and the plugin automatically assigns all the module's flavors to
            // that dimension.
            dimension "version"
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
        }
        full {
            dimension "version"
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
        }
    }
}

หมายเหตุ: หากคุณมีแอปเวอร์ชันเดิม (สร้างก่อนเดือนสิงหาคม 2021) ที่จัดจำหน่ายโดยใช้ APK ใน Google Play หากต้องการจัดจำหน่ายแอปโดยใช้การรองรับ APK หลายรายการใน Google Play ให้กำหนดapplicationIdค่าเดียวกัน ให้กับตัวแปรทั้งหมด และกำหนดversionCode ที่แตกต่างกันให้กับตัวแปรแต่ละรายการ หากต้องการเผยแพร่แอปเวอร์ชันต่างๆ เป็นแอปแยกกันใน Google Play คุณต้องกำหนด applicationId ที่แตกต่างกันให้กับแต่ละเวอร์ชัน

หลังจากสร้างและกำหนดค่าผลิตภัณฑ์แล้ว ให้คลิกซิงค์ เลยในแถบการแจ้งเตือน เมื่อการซิงค์เสร็จสมบูรณ์ Gradle จะสร้างตัวแปรบิลด์โดยอัตโนมัติตามประเภทบิลด์และรสชาติผลิตภัณฑ์ และตั้งชื่อตาม<product-flavor><Build-Type> ตัวอย่างเช่น หากคุณ สร้างรสชาติผลิตภัณฑ์ "demo" และ "full" และเก็บค่าเริ่มต้น ประเภทบิลด์ "debug" และ "release" ไว้ Gradle จะสร้างตัวแปรบิลด์ต่อไปนี้

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

หากต้องการเลือกตัวแปรบิลด์ที่จะสร้างและ เรียกใช้ ให้ไปที่บิลด์ > เลือกตัวแปรบิลด์ แล้วเลือก ตัวแปรบิลด์จากเมนู หากต้องการเริ่มปรับแต่งตัวแปรบิลด์แต่ละรายการด้วยฟีเจอร์และ ทรัพยากรของตัวเอง คุณจะต้องสร้างและจัดการชุดแหล่งที่มาตามที่อธิบายไว้ในหน้านี้

เปลี่ยนรหัสแอปพลิเคชันสำหรับตัวแปรบิลด์

เมื่อคุณสร้าง APK หรือ AAB สำหรับแอป เครื่องมือบิลด์จะติดแท็กแอปด้วย รหัสแอปพลิเคชันที่กำหนดไว้ในบล็อก defaultConfig จากไฟล์ build.gradle.kts ดังที่แสดงในตัวอย่างต่อไปนี้ อย่างไรก็ตาม หากต้องการสร้างแอปเวอร์ชันต่างๆ ให้ปรากฏเป็นข้อมูลแยกกันใน Google Play Store เช่น เวอร์ชัน "ฟรี" และ "โปร" คุณจะต้องสร้างตัวแปรบิลด์แยกกันซึ่งแต่ละตัวแปรจะมีรหัสแอปพลิเคชันที่แตกต่างกัน

ในกรณีนี้ ให้กำหนดแต่ละรุ่นเป็นรสชาติของผลิตภัณฑ์แยกกัน สำหรับแต่ละรสชาติ ภายในบล็อก productFlavors คุณสามารถกำหนดพร็อพเพอร์ตี้ applicationId ใหม่ หรือจะต่อท้ายกลุ่มกับรหัสแอปพลิเคชันเริ่มต้น โดยใช้ applicationIdSuffix แทนก็ได้ ดังที่แสดงที่นี่

Kotlin

android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
        }
    }
}

Groovy

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    productFlavors {
        free {
            applicationIdSuffix ".free"
        }
        pro {
            applicationIdSuffix ".pro"
        }
    }
}

ด้วยวิธีนี้ รหัสแอปพลิเคชันสำหรับผลิตภัณฑ์เวอร์ชัน "ฟรี" จะเป็น "com.example.myapp.free"

นอกจากนี้ คุณยังใช้ applicationIdSuffix เพื่อต่อท้ายกลุ่มตามประเภทบิลด์ได้ด้วย ดังที่แสดงที่นี่

Kotlin

android {
    ...
    buildTypes {
        getByName("debug") {
            applicationIdSuffix = ".debug"
        }
    }
}

Groovy

android {
    ...
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

เนื่องจาก Gradle ใช้การกำหนดค่าประเภทบิลด์หลังจาก Product Flavor รหัสแอปพลิเคชันสำหรับตัวแปรบิลด์ "free debug" คือ "com.example.myapp.free.debug" ซึ่งจะมีประโยชน์เมื่อคุณต้องการมีทั้ง บิลด์การแก้ไขข้อบกพร่องและบิลด์ที่เผยแพร่ในอุปกรณ์เดียวกัน เนื่องจากแอป 2 แอปไม่สามารถมี รหัสแอปพลิเคชันเดียวกันได้

หากคุณมีแอปเดิม (สร้างขึ้นก่อนเดือนสิงหาคม 2021) ที่เผยแพร่โดยใช้ APK ใน Google Play และต้องการใช้ข้อมูลแอปเดียวกันเพื่อเผยแพร่ APK หลายรายการที่แต่ละรายการกำหนดเป้าหมายเป็นการกำหนดค่าอุปกรณ์ที่แตกต่างกัน เช่น ระดับ API คุณต้องใช้รหัสแอปพลิเคชันเดียวกันสำหรับตัวแปรบิลด์แต่ละรายการ แต่ต้องกำหนด versionCode ที่แตกต่างกันให้กับ APK แต่ละรายการ ดูข้อมูลเพิ่มเติมได้ที่หัวข้อการรองรับ APK หลายรายการ การเผยแพร่โดยใช้ AAB จะไม่ได้รับผลกระทบ เนื่องจากใช้ Artifact เดียวที่ใช้รหัสเวอร์ชันและรหัสแอปพลิเคชันเดียวโดยค่าเริ่มต้น

เคล็ดลับ: หากต้องการอ้างอิงรหัสแอปพลิเคชันในไฟล์ ไฟล์ Manifest คุณสามารถใช้ตัวยึดตำแหน่ง ${applicationId} ในแอตทริบิวต์ Manifest ใดก็ได้ ในระหว่างการสร้าง Gradle จะแทนที่แท็กนี้ด้วย รหัสแอปพลิเคชันจริง ดูข้อมูลเพิ่มเติมได้ที่แทรกตัวแปรบิลด์ ลงในไฟล์ Manifest

รวมผลิตภัณฑ์หลายรสชาติเข้ากับมิติข้อมูลรสชาติ

ในบางกรณี คุณอาจต้องการรวมการกำหนดค่าจากผลิตภัณฑ์หลายเวอร์ชัน เช่น คุณอาจต้องการสร้างการกำหนดค่าที่แตกต่างกันสำหรับ Product Flavor "full" และ "demo" ที่อิงตามระดับ API โดยปลั๊กอิน Android Gradle จะช่วยให้คุณสร้างกลุ่ม Product Flavor หลายกลุ่มเป็นมิติข้อมูล Flavor ได้

เมื่อสร้างแอป Gradle จะรวมการกำหนดค่า Product Flavor จากมิติข้อมูล Flavor แต่ละรายการที่คุณกำหนดไว้กับการกำหนดค่าประเภทบิลด์เพื่อสร้างตัวแปรบิลด์สุดท้าย Gradle จะไม่รวม Product Flavor ที่อยู่ใน Flavor Dimension เดียวกัน

ตัวอย่างโค้ดต่อไปนี้ใช้พร็อพเพอร์ตี้ flavorDimensions เพื่อสร้างมิติข้อมูล "โหมด" เพื่อจัดกลุ่มรสชาติผลิตภัณฑ์ "เต็ม" และ "เดโม" และมิติข้อมูลรสชาติ "api" เพื่อจัดกลุ่มการกำหนดค่ารสชาติผลิตภัณฑ์ตามระดับ API

Kotlin

android {
  ...
  buildTypes {
    getByName("debug") {...}
    getByName("release") {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions += listOf("api", "mode")

  productFlavors {
    create("demo") {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension = "mode"
      ...
    }

    create("full") {
      dimension = "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    create("minApi24") {
      dimension = "api"
      minSdk = 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.
      versionCode = 30000 + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi24"
      ...
    }

    create("minApi23") {
      dimension = "api"
      minSdk = 23
      versionCode = 20000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi23"
      ...
    }

    create("minApi21") {
      dimension = "api"
      minSdk = 21
      versionCode = 10000  + (android.defaultConfig.versionCode ?: 0)
      versionNameSuffix = "-minApi21"
      ...
    }
  }
}
...

Groovy

android {
  ...
  buildTypes {
    debug {...}
    release {...}
  }

  // Specifies the flavor dimensions you want to use. The order in which you
  // list the dimensions determines their priority, from highest to lowest,
  // when Gradle merges variant sources and configurations. You must assign
  // each product flavor you configure to one of the flavor dimensions.
  flavorDimensions "api", "mode"

  productFlavors {
    demo {
      // Assigns this product flavor to the "mode" flavor dimension.
      dimension "mode"
      ...
    }

    full {
      dimension "mode"
      ...
    }

    // Configurations in the "api" product flavors override those in "mode"
    // flavors and the defaultConfig block. Gradle determines the priority
    // between flavor dimensions based on the order in which they appear next
    // to the flavorDimensions property, with the first dimension having a higher
    // priority than the second, and so on.
    minApi24 {
      dimension "api"
      minSdkVersion 24
      // To ensure the target device receives the version of the app with
      // the highest compatible API level, assign version codes in increasing
      // value with API level.

      versionCode 30000 + android.defaultConfig.versionCode
      versionNameSuffix "-minApi24"
      ...
    }

    minApi23 {
      dimension "api"
      minSdkVersion 23
      versionCode 20000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi23"
      ...
    }

    minApi21 {
      dimension "api"
      minSdkVersion 21
      versionCode 10000  + android.defaultConfig.versionCode
      versionNameSuffix "-minApi21"
      ...
    }
  }
}
...

จำนวนตัวแปรบิลด์ที่ Gradle สร้างจะเท่ากับผลคูณของ จำนวนรสชาติในมิติรสชาติแต่ละมิติและจำนวนประเภทบิลด์ที่คุณ กำหนดค่า เมื่อ Gradle ตั้งชื่อตัวแปรบิลด์แต่ละรายการหรืออาร์ติแฟกต์ที่เกี่ยวข้อง รสชาติของผลิตภัณฑ์ ที่อยู่ในมิติข้อมูลรสชาติที่มีลำดับความสำคัญสูงกว่าจะปรากฏก่อน ตามด้วย รสชาติจากมิติข้อมูลที่มีลำดับความสำคัญต่ำกว่า และตามด้วยประเภทบิลด์

เมื่อใช้การกำหนดค่าบิลด์ก่อนหน้าเป็นตัวอย่าง Gradle จะสร้างตัวแปรบิลด์ทั้งหมด 12 รายการโดยใช้รูปแบบการตั้งชื่อต่อไปนี้

  • ตัวแปรบิลด์: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
  • APK ที่เกี่ยวข้อง: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
  • ตัวอย่างเช่น
    ตัวแปรบิลด์: minApi24DemoDebug
    APK ที่เกี่ยวข้อง: app-minApi24-demo-debug.apk

นอกเหนือจากไดเรกทอรีชุดแหล่งที่มาที่คุณสร้างสำหรับแต่ละ รสชาติของผลิตภัณฑ์และรุ่นที่สร้างแล้ว คุณยังสร้างไดเรกทอรีชุดแหล่งที่มา สำหรับชุดค่าผสมแต่ละชุดของรสชาติของผลิตภัณฑ์ได้ด้วย เช่น คุณสร้าง และเพิ่มแหล่งที่มาของ Java ไปยังไดเรกทอรี src/demoMinApi24/java/ ได้ และ Gradle จะใช้แหล่งที่มาเหล่านั้นเฉพาะเมื่อสร้างตัวแปรที่รวม รสชาติของผลิตภัณฑ์ทั้ง 2 รายการนั้น

ชุดแหล่งข้อมูลที่คุณสร้างขึ้นสำหรับชุดค่าผสมรสชาติของผลิตภัณฑ์ จะมีลำดับความสำคัญสูงกว่าชุดแหล่งข้อมูลที่อยู่ในรสชาติของผลิตภัณฑ์แต่ละรายการ ดูข้อมูลเพิ่มเติมเกี่ยวกับชุดแหล่งที่มาและวิธีที่ Gradle ผสานรวมทรัพยากรได้ที่ส่วนเกี่ยวกับวิธีสร้าง ชุดแหล่งที่มา

กรองตัวแปร

Gradle จะสร้างตัวแปรบิลด์สำหรับชุดค่าผสมที่เป็นไปได้ทั้งหมดของ Product Flavors และประเภทบิลด์ที่คุณกำหนดค่า อย่างไรก็ตาม อาจมี ตัวแปรบิลด์บางรายการที่คุณไม่ต้องการหรือไม่มีประโยชน์ใน บริบทของโปรเจ็กต์ หากต้องการนำการกำหนดค่าตัวแปรบิลด์บางรายการออก ให้สร้างตัวกรองตัวแปรในไฟล์ build.gradle.kts ระดับโมดูล

ใช้การกำหนดค่าบิลด์จากส่วนก่อนหน้าเป็นตัวอย่าง สมมติว่าคุณวางแผนที่จะรองรับเฉพาะระดับ API 23 ขึ้นไปสำหรับเวอร์ชัน สาธิตของแอป คุณสามารถใช้บล็อก variantFilter เพื่อกรองการกำหนดค่าตัวแปรบิลด์ทั้งหมด ที่รวมรสชาติผลิตภัณฑ์ "minApi21" และ "demo" ได้ดังนี้

Kotlin

android {
  ...
  buildTypes {...}

  flavorDimensions += listOf("api", "mode")
  productFlavors {
    create("demo") {...}
    create("full") {...}
    create("minApi24") {...}
    create("minApi23") {...}
    create("minApi21") {...}
  }
}

androidComponents {
    beforeVariants { variantBuilder ->
        // To check for a certain build type, use variantBuilder.buildType == "<buildType>"
        if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
            // Gradle ignores any variants that satisfy the conditions above.
            variantBuilder.enable = false
        }
    }
}
...

Groovy

android {
  ...
  buildTypes {...}

  flavorDimensions "api", "mode"
  productFlavors {
    demo {...}
    full {...}
    minApi24 {...}
    minApi23 {...}
    minApi21 {...}
  }

  variantFilter { variant ->
      def names = variant.flavors*.name
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
      if (names.contains("minApi21") && names.contains("demo")) {
          // Gradle ignores any variants that satisfy the conditions above.
          setIgnore(true)
      }
  }
}
...

เมื่อเพิ่มตัวกรองตัวแปรไปยังการกำหนดค่าบิลด์แล้วคลิกซิงค์ ตอนนี้ในแถบการแจ้งเตือน Gradle จะไม่สนใจตัวแปรบิลด์ใดๆ ที่ตรงกับ เงื่อนไขที่คุณระบุ ตัวแปรบิลด์จะไม่ปรากฏในเมนูอีกต่อไป เมื่อคุณคลิกบิลด์ > เลือกตัวแปรบิลด์จากแถบเมนู หรือตัวแปรบิลด์ ใน แถบหน้าต่างเครื่องมือ

สร้างชุดแหล่งที่มา

โดยค่าเริ่มต้น Android Studio จะสร้างmain/ ชุดแหล่งที่มาและไดเรกทอรีสำหรับ ทุกอย่างที่คุณต้องการแชร์ระหว่างตัวแปรบิลด์ทั้งหมด อย่างไรก็ตาม คุณ สามารถสร้างชุดแหล่งที่มาใหม่เพื่อควบคุมว่า Gradle จะคอมไพล์และ แพ็กเกจไฟล์ใดสำหรับประเภทบิลด์ รสชาติของผลิตภัณฑ์ ชุดค่าผสมของ รสชาติของผลิตภัณฑ์ (เมื่อใช้มิติข้อมูลรสชาติ) และตัวแปรบิลด์

เช่น คุณสามารถกำหนดฟังก์ชันพื้นฐานในmain/ชุดแหล่งที่มาและใช้ชุดแหล่งที่มาของ Product Flavor เพื่อเปลี่ยนการสร้างแบรนด์ของแอปสำหรับไคลเอ็นต์ต่างๆ หรือ รวมสิทธิ์พิเศษและฟังก์ชันการบันทึกเฉพาะสำหรับตัวแปรบิลด์ ที่ใช้ประเภทบิลด์สำหรับแก้ไขข้อบกพร่อง

Gradle คาดหวังให้จัดระเบียบไฟล์และไดเรกทอรีของชุดแหล่งที่มาในลักษณะหนึ่ง ซึ่งคล้ายกับmain/ชุดแหล่งที่มา ตัวอย่างเช่น Gradle คาดหวังให้ไฟล์คลาส Kotlin หรือ Java ที่เฉพาะเจาะจงกับประเภทบิลด์ "debug" อยู่ใน ไดเรกทอรี src/debug/kotlin/ หรือ src/debug/java/

ปลั๊กอิน Android Gradle มีงาน Gradle ที่มีประโยชน์ซึ่งจะแสดงวิธีจัดระเบียบไฟล์สำหรับประเภทบิลด์ รสชาติของผลิตภัณฑ์ และตัวแปรบิลด์แต่ละรายการ ตัวอย่างเช่น ตัวอย่างต่อไปนี้จากเอาต์พุตของงาน อธิบายตำแหน่งที่ Gradle คาดว่าจะพบไฟล์บางอย่างสำหรับบิลด์ประเภท "debug"

------------------------------------------------------------
Project :app
------------------------------------------------------------

...

debug
----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Kotlin sources: [app/src/debug/kotlin, app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]

หากต้องการดูเอาต์พุตนี้ ให้ทำตามขั้นตอนต่อไปนี้

  1. คลิก Gradle ในแถบหน้าต่างเครื่องมือ
  2. ไปที่ MyApplication > Tasks > android แล้ว ดับเบิลคลิก sourceSets

    หากต้องการดูโฟลเดอร์ Tasks คุณต้องอนุญาตให้ Gradle สร้างรายการงาน ระหว่างการซิงค์ โดยทำตามขั้นตอนต่อไปนี้

    1. คลิกไฟล์ > การตั้งค่า > ทดลอง (Android Studio > การตั้งค่า > ทดลอง ใน macOS)
    2. ยกเลิกการเลือกไม่ต้อง สร้างรายการงาน Gradle ระหว่างการซิงค์ Gradle
  3. หลังจาก Gradle ดำเนินการในงานแล้ว หน้าต่างเรียกใช้จะเปิดขึ้นเพื่อแสดงเอาต์พุต

หมายเหตุ: เอาต์พุตของงานยังแสดงวิธีจัดระเบียบชุดแหล่งที่มา สำหรับไฟล์ที่คุณต้องการใช้เพื่อเรียกใช้การทดสอบสำหรับแอป เช่น test/ และ androidTest/ ชุดแหล่งที่มาสำหรับการทดสอบ

เมื่อสร้างตัวแปรบิลด์ใหม่ Android Studio จะไม่สร้างไดเรกทอรีชุดแหล่งที่มาให้ แต่จะมีตัวเลือก 2-3 อย่างที่จะช่วยคุณได้ เช่น หากต้องการสร้างเฉพาะไดเรกทอรี java/ สำหรับประเภทบิลด์ "debug" ให้ทำดังนี้

  1. เปิดแผงโปรเจ็กต์ แล้วเลือกมุมมองโปรเจ็กต์จากเมนูที่ด้านบนของแผง
  2. ไปที่ MyProject/app/src/
  3. คลิกขวาที่ไดเรกทอรี src แล้วเลือก ใหม่ > ไดเรกทอรี
  4. จากเมนูในส่วนชุดแหล่งที่มาของ Gradle ให้เลือก full/java
  5. กด Enter

Android Studio จะสร้างไดเรกทอรีชุดแหล่งที่มาสำหรับประเภทบิลด์การแก้ไขข้อบกพร่อง และ จากนั้นจะสร้างไดเรกทอรี java/ ภายใน หรือ Android Studio จะสร้างไดเรกทอรีให้คุณเมื่อเพิ่มไฟล์ใหม่ลงใน โปรเจ็กต์สำหรับตัวแปรบิลด์ที่เฉพาะเจาะจง

เช่น หากต้องการสร้างไฟล์ XML ของค่าสำหรับประเภทบิลด์ "debug" ให้ทำดังนี้

  1. ในแผงโปรเจ็กต์ ให้คลิกขวาที่ไดเรกทอรี src แล้วเลือกใหม่ > XML > ไฟล์ XML ของค่า
  2. ป้อนชื่อไฟล์ XML หรือใช้ชื่อเริ่มต้น
  3. จากเมนูข้างชุดแหล่งข้อมูลเป้าหมาย ให้เลือก debug
  4. คลิกเสร็จสิ้น

เนื่องจากมีการระบุประเภทบิลด์ "debug" เป็นชุดแหล่งที่มาเป้าหมาย Android Studio จึงสร้างไดเรกทอรีที่จำเป็นโดยอัตโนมัติเมื่อสร้างไฟล์ XML โครงสร้างไดเรกทอรีที่ได้จะมีลักษณะดังรูปที่ 1

รูปที่ 1 ไดเรกทอรีชุดแหล่งที่มาใหม่สำหรับบิลด์ประเภท "debug"

ชุดแหล่งที่มาที่ใช้งานอยู่จะมีสัญญาณบอกสถานะสีเขียวในไอคอนเพื่อแสดงว่าชุดดังกล่าวใช้งานอยู่ debug ชุดแหล่งข้อมูลจะต่อท้ายด้วย [main] เพื่อแสดงว่าระบบจะผสานชุดแหล่งข้อมูลนี้ เข้ากับชุดแหล่งข้อมูล main

คุณยังสร้างไดเรกทอรีชุดแหล่งที่มาสำหรับ รสชาติของผลิตภัณฑ์ เช่น src/demo/ และสร้างตัวแปร เช่น src/demoDebug/ ได้ด้วยขั้นตอนเดียวกัน นอกจากนี้ คุณยังสร้างชุดแหล่งข้อมูลการทดสอบ ที่กำหนดเป้าหมายไปยังตัวแปรบิลด์ที่เฉพาะเจาะจงได้ด้วย เช่น src/androidTestDemoDebug/ ดูข้อมูลเพิ่มเติมได้ที่หัวข้อเกี่ยวกับ การทดสอบชุดแหล่งที่มา

เปลี่ยนการกำหนดค่าชุดแหล่งข้อมูลเริ่มต้น

หากมีแหล่งที่มาที่ไม่ได้จัดระเบียบไว้ในไฟล์ชุดแหล่งที่มาเริ่มต้น ตามโครงสร้างที่ Gradle คาดหวัง ดังที่อธิบายไว้ในส่วนก่อนหน้าเกี่ยวกับ การสร้างชุดแหล่งที่มา คุณสามารถใช้บล็อก sourceSets เพื่อเปลี่ยนตำแหน่งที่ Gradle ค้นหาเพื่อรวบรวม ไฟล์สำหรับแต่ละคอมโพเนนต์ของชุดแหล่งที่มา

บล็อก sourceSets ต้องอยู่ในบล็อก android คุณไม่จำเป็นต้องย้ายไฟล์ต้นฉบับ เพียงแค่ระบุเส้นทางที่สัมพันธ์กับไฟล์ build.gradle.kts ระดับโมดูลให้ Gradle เพื่อให้ Gradle ค้นหาไฟล์สำหรับคอมโพเนนต์แต่ละชุดแหล่งที่มาได้ ดูว่าคุณกำหนดค่าคอมโพเนนต์ใดได้บ้างและจะแมปกับไฟล์หรือไดเรกทอรีหลายรายการได้หรือไม่ที่เอกสารอ้างอิง API ของปลั๊กอิน Android Gradle

ตัวอย่างโค้ดต่อไปนี้จะแมปแหล่งที่มาจากไดเรกทอรี app/other/ ไปยังคอมโพเนนต์บางอย่างของชุดแหล่งที่มา main และเปลี่ยน ไดเรกทอรีรากของชุดแหล่งที่มา androidTest

Kotlin

android {
  ...
  // Encapsulates configurations for the main source set.
  sourceSets.getByName("main") {
    // Changes the directory for Java sources. The default directory is
    // 'src/main/java'.
    java.setSrcDirs(listOf("other/java"))

    // If you list multiple directories, Gradle uses all of them to collect
    // sources. Because Gradle gives these directories equal priority, if
    // you define the same resource in more than one directory, you receive an
    // error when merging resources. The default directory is 'src/main/res'.
    res.setSrcDirs(listOf("other/res1", "other/res2"))

    // Note: Avoid specifying a directory that is a parent to one
    // or more other directories you specify. For example, avoid the following:
    // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
    // Specify either only the root 'other/res1' directory or only the
    // nested 'other/res1/layouts' and 'other/res1/strings' directories.

    // For each source set, you can specify only one Android manifest.
    // By default, Android Studio creates a manifest for your main source
    // set in the src/main/ directory.
    manifest.srcFile("other/AndroidManifest.xml")
    ...
  }

  // Create additional blocks to configure other source sets.
  sourceSets.getByName("androidTest") {
      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot("src/tests")
      ...
  }
}
...

Groovy

android {
  ...
  sourceSets {
    // Encapsulates configurations for the main source set.
    main {
      // Changes the directory for Java sources. The default directory is
      // 'src/main/java'.
      java.srcDirs = ['other/java']

      // If you list multiple directories, Gradle uses all of them to collect
      // sources. Because Gradle gives these directories equal priority, if
      // you define the same resource in more than one directory, you receive an
      // error when merging resources. The default directory is 'src/main/res'.
      res.srcDirs = ['other/res1', 'other/res2']

      // Note: Avoid specifying a directory that is a parent to one
      // or more other directories you specify. For example, avoid the following:
      // res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
      // Specify either only the root 'other/res1' directory or only the
      // nested 'other/res1/layouts' and 'other/res1/strings' directories.

      // For each source set, you can specify only one Android manifest.
      // By default, Android Studio creates a manifest for your main source
      // set in the src/main/ directory.
      manifest.srcFile 'other/AndroidManifest.xml'
      ...
    }

    // Create additional blocks to configure other source sets.
    androidTest {

      // If all the files for a source set are located under a single root
      // directory, you can specify that directory using the setRoot property.
      // When gathering sources for the source set, Gradle looks only in locations
      // relative to the root directory you specify. For example, after applying the
      // configuration below for the androidTest source set, Gradle looks for Java
      // sources only in the src/tests/java/ directory.
      setRoot 'src/tests'
      ...
    }
  }
}
...

โปรดทราบว่าไดเรกทอรีแหล่งที่มาจะเป็นของชุดแหล่งที่มาได้เพียงชุดเดียวเท่านั้น เช่น คุณแชร์แหล่งที่มาของการทดสอบเดียวกันกับทั้งชุดแหล่งที่มา test และ androidTest ไม่ได้ เนื่องจาก Android Studio จะสร้างโมดูล IntelliJ แยกต่างหากสำหรับแต่ละชุดแหล่งที่มาและไม่รองรับรูทเนื้อหาที่ซ้ำกันในชุดแหล่งที่มา

สร้างด้วยชุดแหล่งที่มา

คุณใช้ไดเรกทอรีชุดแหล่งที่มาเพื่อเก็บโค้ดและทรัพยากรที่ต้องการ แพ็กเกจเฉพาะกับการกำหนดค่าบางอย่างได้ ตัวอย่างเช่น หากคุณกำลังสร้างตัวแปรบิลด์ "demoDebug" ซึ่งเป็นผลิตภัณฑ์ข้ามผลิตภัณฑ์ของรสชาติผลิตภัณฑ์ "demo" และประเภทบิลด์ "debug" Gradle จะดูไดเรกทอรีเหล่านี้และกำหนดลำดับความสำคัญต่อไปนี้

  1. src/demoDebug/ (ชุดแหล่งที่มาของตัวแปรบิลด์)
  2. src/debug/ (ชุดแหล่งที่มาของประเภทบิลด์)
  3. src/demo/ (ชุดแหล่งที่มาของเวอร์ชันผลิตภัณฑ์)
  4. src/main/ (ชุดแหล่งข้อมูลหลัก)

ชุดแหล่งข้อมูลที่สร้างขึ้นสำหรับชุดค่าผสมของรสชาติผลิตภัณฑ์ต้องมีมิติข้อมูลรสชาติทั้งหมด เช่น ชุดแหล่งที่มาของตัวแปรบิลด์ต้องเป็นการรวมกันของประเภทบิลด์และมิติข้อมูลรสชาติทั้งหมด ระบบไม่รองรับการผสานโค้ดและทรัพยากรที่เกี่ยวข้องกับโฟลเดอร์ซึ่งครอบคลุมมิติข้อมูลรสชาติหลายรายการแต่ไม่ใช่ทั้งหมด

หากรวมรสชาติของผลิตภัณฑ์หลายรายการ ระบบจะกำหนดลำดับความสำคัญระหว่างรสชาติของผลิตภัณฑ์ตามมิติข้อมูลรสชาติ ที่รสชาติเหล่านั้นสังกัดอยู่ เมื่อแสดงมิติข้อมูลรสชาติด้วยพร็อพเพอร์ตี้ android.flavorDimensions รสชาติของผลิตภัณฑ์ที่ อยู่ในมิติข้อมูลรสชาติแรกที่คุณแสดงจะมีลำดับความสำคัญสูงกว่า รสชาติที่อยู่ในมิติข้อมูลรสชาติที่สอง และอื่นๆ นอกจากนี้ ชุดแหล่งข้อมูลที่คุณสร้างขึ้นสำหรับชุดค่าผสมของรสชาติผลิตภัณฑ์จะมีลำดับความสำคัญสูงกว่า ชุดแหล่งข้อมูลที่เป็นของรสชาติผลิตภัณฑ์แต่ละรายการ

ลำดับความสำคัญจะเป็นตัวกำหนดว่าชุดแหล่งข้อมูลใดมีลำดับความสำคัญสูงกว่า เมื่อ Gradle รวมโค้ดและทรัพยากร เนื่องจากไดเรกทอรีชุดแหล่งที่มา demoDebug/ น่าจะมีไฟล์ที่เฉพาะเจาะจงกับตัวแปรบิลด์นั้น หาก demoDebug/ มีไฟล์ที่กำหนดไว้ใน debug/ ด้วย Gradle จะใช้ไฟล์ในชุดแหล่งที่มา demoDebug/ ในทำนองเดียวกัน Gradle จะให้ความสำคัญกับไฟล์ในแหล่งที่มาของประเภทบิลด์และ Product Flavor มากกว่าไฟล์เดียวกันใน main/ Gradle จะพิจารณาลำดับความสำคัญนี้เมื่อใช้กฎการสร้างต่อไปนี้

  • ระบบจะคอมไพล์ซอร์สโค้ดทั้งหมดในไดเรกทอรี kotlin/ หรือ java/ ร่วมกันเพื่อสร้างเอาต์พุตเดียว

    หมายเหตุ: สำหรับตัวแปรบิลด์ที่กำหนด Gradle จะแสดงข้อผิดพลาดในการบิลด์ หากพบไดเรกทอรีชุดแหล่งข้อมูลอย่างน้อย 2 รายการที่กำหนด คลาส Kotlin หรือ Java เดียวกัน เช่น เมื่อสร้างแอปสำหรับแก้ไขข้อบกพร่อง คุณจะ กำหนดทั้ง src/debug/Utility.kt และ src/main/Utility.kt ไม่ได้ เนื่องจาก Gradle จะดูทั้ง ไดเรกทอรีเหล่านี้ในระหว่างกระบวนการบิลด์และแสดงข้อผิดพลาด "คลาสซ้ำ" หากต้องการใช้ Utility.kt เวอร์ชันอื่นสำหรับ ประเภทบิลด์ต่างๆ แต่ละประเภทบิลด์ต้องกำหนดเวอร์ชันของ ไฟล์ของตัวเองและไม่รวมไว้ในชุดแหล่งที่มาของ main/

  • ระบบจะผสานไฟล์ Manifest เข้าด้วยกันเป็นไฟล์ Manifest เดียว ระบบจะให้ความสำคัญ ตามลำดับเดียวกับรายการในตัวอย่างก่อนหน้า กล่าวคือ การตั้งค่าไฟล์ Manifest สำหรับประเภทบิลด์ จะลบล้างการตั้งค่าไฟล์ Manifest สำหรับ Product Flavor และอื่นๆ ดูข้อมูลเพิ่มเติมได้ที่การผสานไฟล์ Manifest
  • ระบบจะผสานไฟล์ในไดเรกทอรี values/ เข้าด้วยกัน หากไฟล์ 2 ไฟล์มีชื่อเดียวกัน เช่น ไฟล์ 2 ไฟล์ strings.xml ระบบจะให้ลำดับความสำคัญตามลำดับเดียวกับ รายการในตัวอย่างก่อนหน้า กล่าวคือ ค่าที่กำหนดไว้ในไฟล์ในชุดแหล่งที่มาของประเภทบิลด์ จะลบล้างค่าที่กำหนดไว้ในไฟล์เดียวกันใน Product Flavor และอื่นๆ
  • ระบบจะแพ็กเกจทรัพยากรในไดเรกทอรี res/ และ asset/ ไว้ด้วยกัน หากมีทรัพยากรที่มีชื่อเดียวกันซึ่งกำหนดไว้ใน ชุดแหล่งที่มา 2 ชุดขึ้นไป ระบบจะให้ลำดับความสำคัญตามลำดับเดียวกับรายการ ในตัวอย่างก่อนหน้า
  • Gradle จะให้ความสำคัญกับทรัพยากรและไฟล์ Manifest ที่รวมอยู่ในทรัพยากร Dependency ของโมดูลไลบรารี น้อยที่สุดเมื่อสร้างแอป

ประกาศทรัพยากร Dependency

หากต้องการกําหนดค่าการขึ้นต่อกันสําหรับรูปแบบบิลด์หรือชุดแหล่งที่มาของการทดสอบที่เฉพาะเจาะจง ให้ใส่คํานําหน้าชื่อรูปแบบบิลด์หรือชุดแหล่งที่มาของการทดสอบก่อนคีย์เวิร์ด Implementation ดังที่แสดงในตัวอย่างต่อไปนี้

Kotlin

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    "freeImplementation"(project(":mylibrary"))

    // Adds a remote binary dependency only for local tests.
    testImplementation("junit:junit:4.12")

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation("com.android.support.test.espresso:espresso-core:3.6.1")
}

Groovy

dependencies {
    // Adds the local "mylibrary" module as a dependency to the "free" flavor.
    freeImplementation project(":mylibrary")

    // Adds a remote binary dependency only for local tests.
    testImplementation 'junit:junit:4.12'

    // Adds a remote binary dependency only for the instrumented test APK.
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.6.1'
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าการขึ้นต่อกันได้ที่เพิ่มการขึ้นต่อกันของบิลด์

ใช้การจัดการการขึ้นต่อกันที่รับรู้ตัวแปร

ปลั๊กอิน Android Gradle 3.0.0 ขึ้นไปมีกลไกการพึ่งพาใหม่ที่จับคู่ตัวแปรโดยอัตโนมัติ เมื่อใช้ไลบรารี ซึ่งหมายความว่าdebug รูปแบบ ของแอปจะใช้debug รูปแบบของไลบรารีโดยอัตโนมัติ และอื่นๆ นอกจากนี้ยังใช้ได้เมื่อใช้ Flavor ด้วย กล่าวคือ ตัวแปร freeDebug ของแอปจะใช้ตัวแปร freeDebug ของไลบรารี

หากต้องการให้ปลั๊กอินจับคู่ตัวแปรได้อย่างถูกต้อง คุณต้อง ระบุการสำรองข้อมูลที่ตรงกันตามที่อธิบายไว้ใน ส่วนต่อไปนี้ ในกรณีที่ไม่สามารถจับคู่โดยตรงได้

ตัวอย่างเช่น สมมติว่าแอปของคุณกำหนดค่าประเภทบิลด์ที่ชื่อ "staging" แต่การอ้างอิงไลบรารีอย่างใดอย่างหนึ่ง ไม่ได้กำหนดค่า เมื่อปลั๊กอินพยายามสร้างแอปเวอร์ชัน "สเตจ" ปลั๊กอินจะไม่ทราบว่าจะใช้ไลบรารีเวอร์ชันใด และคุณจะเห็นข้อความแสดงข้อผิดพลาดที่คล้ายกับ ข้อความต่อไปนี้

Error:Failed to resolve: Could not resolve project :mylibrary.
Required by:
    project :app

แก้ไขข้อผิดพลาดในการสร้างที่เกี่ยวข้องกับการจับคู่ตัวแปร

ปลั๊กอินมีองค์ประกอบ DSL ที่ช่วยให้คุณควบคุมวิธีที่ Gradle แก้ไขสถานการณ์ที่แอปและ Dependency ไม่สามารถจับคู่ตัวแปรโดยตรงได้

ต่อไปนี้คือรายการปัญหาที่เกี่ยวข้องกับการจับคู่การอ้างอิงที่รับรู้ถึงตัวแปรและวิธี แก้ปัญหาโดยใช้พร็อพเพอร์ตี้ DSL

  • แอปของคุณมีประเภทบิลด์ที่ทรัพยากร Dependency ของไลบรารีไม่มี

    เช่น แอปของคุณมีประเภทบิลด์ "staging" แต่การขึ้นต่อกันมีเฉพาะประเภทบิลด์ "debug" และ "release"

    โปรดทราบว่าไม่มีปัญหาเมื่อการอ้างอิงไลบรารีมีประเภทบิลด์ ที่แอปของคุณไม่มี เนื่องจากปลั๊กอินไม่เคย ขอประเภทบิลด์นั้นจาก Dependency

    ใช้ matchingFallbacks เพื่อระบุการจับคู่สำรองสำหรับประเภทบิลด์ที่กำหนด ดังที่แสดงที่นี่

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        buildTypes {
            getByName("debug") {}
            getByName("release") {}
            create("staging") {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks += listOf("debug", "qa", "release")
            }
        }
    }

    Groovy

    // In the app's build.gradle file.
    android {
        buildTypes {
            debug {}
            release {}
            staging {
                // Specifies a sorted list of fallback build types that the
                // plugin can try to use when a dependency does not include a
                // "staging" build type. You may specify as many fallbacks as you
                // like, and the plugin selects the first build type that's
                // available in the dependency.
                matchingFallbacks = ['debug', 'qa', 'release']
            }
        }
    }
  • สำหรับมิติข้อมูลรสชาติที่กำหนดซึ่งมีอยู่ในทั้งแอปและทรัพยากร Dependency ของไลบรารี แอปจะมีรสชาติที่ไลบรารีไม่มี

    เช่น ทั้งแอปและทรัพยากร Dependency ของไลบรารีมีมิติข้อมูลรสชาติ "ระดับ" อย่างไรก็ตาม มิติข้อมูล "ระดับ" ในแอปมีทั้งแบบ "ฟรี" และ "แบบชำระเงิน" แต่ การอ้างอิงมีเฉพาะแบบ "เดโม" และ "แบบชำระเงิน" สำหรับมิติข้อมูลเดียวกัน

    โปรดทราบว่าสำหรับมิติข้อมูลรสชาติที่กำหนดซึ่งมีอยู่ในทั้งแอปและทรัพยากร Dependency ของไลบรารี จะไม่มีปัญหาเมื่อไลบรารีมีรสชาติของผลิตภัณฑ์ที่แอปของคุณไม่มี เนื่องจากปลั๊กอินไม่เคยขอรสชาตินั้นจาก Dependency

    ใช้ matchingFallbacks เพื่อระบุการจับคู่ทางเลือกสำหรับรสชาติผลิตภัณฑ์ "ฟรี" ของแอป ดังที่แสดงที่นี่

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions += "tier"
        productFlavors {
            create("paid") {
                dimension = "tier"
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            create("free") {
                dimension = "tier"
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks += listOf("demo", "trial")
            }
        }
    }

    Groovy

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Don't configure matchingFallbacks in the defaultConfig block.
        // Instead, specify fallbacks for a given product flavor in the
        // productFlavors block, as shown below.
      }
        flavorDimensions 'tier'
        productFlavors {
            paid {
                dimension 'tier'
                // Because the dependency already includes a "paid" flavor in its
                // "tier" dimension, you don't need to provide a list of fallbacks
                // for the "paid" flavor.
            }
            free {
                dimension 'tier'
                // Specifies a sorted list of fallback flavors that the plugin
                // can try to use when a dependency's matching dimension does
                // not include a "free" flavor. Specify as many
                // fallbacks as you like; the plugin selects the first flavor
                // that's available in the dependency's "tier" dimension.
                matchingFallbacks = ['demo', 'trial']
            }
        }
    }
  • ทรัพยากร Dependency ของไลบรารีมีมิติข้อมูลรสชาติที่แอปของคุณไม่มี

    ตัวอย่างเช่น ทรัพยากร Dependency ของไลบรารีมี Flavor สำหรับมิติข้อมูล "minApi" แต่แอปของคุณ มี Flavor สำหรับมิติข้อมูล "tier" เท่านั้น เมื่อคุณต้องการสร้างแอปเวอร์ชัน "freeDebug" ปลั๊กอินจะไม่ทราบว่าจะใช้เวอร์ชัน "minApi23Debug" หรือ "minApi18Debug" ของการขึ้นต่อกัน

    โปรดทราบว่าไม่มีปัญหาเมื่อแอปของคุณมีมิติข้อมูลรสชาติที่การอ้างอิงไลบรารีไม่มี เนื่องจากปลั๊กอินจะจับคู่ Flavor ของเฉพาะมิติข้อมูลที่ อยู่ใน Dependency เช่น หากการอ้างอิงไม่มีมิติข้อมูลสำหรับ ABI แอปเวอร์ชัน "freeX86Debug" จะใช้เวอร์ชัน "freeDebug" ของ การอ้างอิง

    ใช้ missingDimensionStrategy ในบล็อก defaultConfig เพื่อระบุ รสชาติเริ่มต้นสำหรับปลั๊กอินที่จะเลือกจากมิติข้อมูลที่ขาดหายไปแต่ละรายการ ดังที่แสดงใน ตัวอย่างต่อไปนี้ นอกจากนี้ คุณยังลบล้างการเลือกในบล็อก productFlavors ได้ด้วย เพื่อให้แต่ละรสชาติระบุกลยุทธ์การจับคู่ที่แตกต่างกันสำหรับมิติข้อมูลที่ขาดหายไป

    Kotlin

    // In the app's build.gradle.kts file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy("minApi", "minApi18", "minApi23")
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy("abi", "x86", "arm64")
        }
        flavorDimensions += "tier"
        productFlavors {
            create("free") {
                dimension = "tier"
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the "minApi" dimension.
                missingDimensionStrategy("minApi", "minApi23", "minApi18")
            }
            create("paid") {}
        }
    }

    Groovy

    // In the app's build.gradle file.
    android {
        defaultConfig{
        // Specifies a sorted list of flavors that the plugin can try to use from
        // a given dimension. This tells the plugin to select the "minApi18" flavor
        // when encountering a dependency that includes a "minApi" dimension.
        // You can include additional flavor names to provide a
        // sorted list of fallbacks for the dimension.
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
        // Specify a missingDimensionStrategy property for each
        // dimension that exists in a local dependency but not in your app.
        missingDimensionStrategy 'abi', 'x86', 'arm64'
        }
        flavorDimensions 'tier'
        productFlavors {
            free {
                dimension 'tier'
                // You can override the default selection at the product flavor
                // level by configuring another missingDimensionStrategy property
                // for the 'minApi' dimension.
                missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
            }
            paid {}
        }
    }

ดูข้อมูลเพิ่มเติมได้ที่ matchingFallbacks และ missingDimensionStrategy ในข้อมูลอ้างอิง DSL ของปลั๊กอิน Android Gradle

กำหนดการตั้งค่าการลงนาม

Gradle จะไม่ลงนามใน APK หรือ AAB ของบิลด์รุ่นที่เผยแพร่ เว้นแต่คุณจะกำหนดค่าการลงนามสำหรับบิลด์นี้อย่างชัดเจน หากยังไม่มีคีย์การลงนาม ให้สร้างคีย์การอัปโหลดและที่เก็บคีย์ โดยใช้ Android Studio

หากต้องการกำหนดค่าการลงนามสำหรับประเภทบิลด์รุ่นด้วยตนเอง โดยใช้การกำหนดค่าบิลด์ Gradle ให้ทำดังนี้

  1. สร้างคีย์สโตร์ คีย์สโตร์คือไฟล์ไบนารี ที่มีชุดคีย์ส่วนตัว คุณต้องเก็บคีย์สโตร์ไว้ในที่ที่ปลอดภัย
  2. สร้างคีย์ส่วนตัว คีย์ส่วนตัวใช้เพื่อลงนามในแอป สำหรับการเผยแพร่ และจะไม่รวมไว้กับแอปหรือเปิดเผยต่อบุคคลที่สามที่ไม่ได้รับอนุญาต
  3. เพิ่มการกำหนดค่าการลงนามลงในไฟล์ build.gradle.kts ระดับโมดูล

    Kotlin

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            create("release") {
                storeFile = file("myreleasekey.keystore")
                storePassword = "password"
                keyAlias = "MyReleaseKey"
                keyPassword = "password"
            }
        }
        buildTypes {
            getByName("release") {
                ...
                signingConfig = signingConfigs.getByName("release")
            }
        }
    }

    Groovy

    ...
    android {
        ...
        defaultConfig {...}
        signingConfigs {
            release {
                storeFile file("myreleasekey.keystore")
                storePassword "password"
                keyAlias "MyReleaseKey"
                keyPassword "password"
            }
        }
        buildTypes {
            release {
                ...
                signingConfig signingConfigs.release
            }
        }
    }

หมายเหตุ: การใส่รหัสผ่านสำหรับคีย์รุ่นและ keystore ไว้ในไฟล์บิลด์ไม่ใช่แนวทางปฏิบัติที่ดีด้านความปลอดภัย แต่ให้กำหนดค่าไฟล์บิลด์เพื่อรับรหัสผ่านเหล่านี้จากตัวแปรสภาพแวดล้อม หรือให้กระบวนการบิลด์แจ้งให้คุณป้อนรหัสผ่านเหล่านี้แทน

วิธีรับรหัสผ่านเหล่านี้จากตัวแปรสภาพแวดล้อม

Kotlin

storePassword = System.getenv("KSTOREPWD")
keyPassword = System.getenv("KEYPWD")

Groovy

storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")

หรือจะโหลดที่เก็บคีย์จากไฟล์พร็อพเพอร์ตี้ในเครื่องก็ได้ เพื่อความปลอดภัย โปรดอย่า เพิ่มไฟล์นี้ลงในการควบคุมแหล่งที่มา แต่ให้ตั้งค่าในเครื่องสำหรับนักพัฒนาแอปแต่ละคนแทน ดูข้อมูลเพิ่มเติมได้ที่ นำข้อมูลการลงนามออกจากไฟล์บิลด์

หลังจากดำเนินการตามกระบวนการนี้เสร็จแล้ว คุณจะสามารถเผยแพร่และเผยแพร่แอปใน Google Play ได้

คำเตือน: โปรดเก็บคีย์สโตร์และคีย์ส่วนตัวไว้ในที่ที่ปลอดภัย และตรวจสอบว่าคุณได้สำรองข้อมูลดังกล่าวอย่างปลอดภัย หากใช้ Play App Signing และคีย์การอัปโหลดสูญหาย คุณสามารถขอรีเซ็ตโดยใช้ Play Console ได้ หากคุณเผยแพร่แอปโดยไม่ใช้ Play App Signing (สำหรับแอปที่สร้างขึ้นก่อนเดือนสิงหาคม 2021) และทำคีย์ App Signing หาย คุณจะเผยแพร่อัปเดตแอปไม่ได้ เนื่องจากคุณต้องลงนามในแอปทุกเวอร์ชันด้วยคีย์เดียวกันเสมอ

การลงนามในแอป Wear OS

เมื่อเผยแพร่แอป Wear OS ทั้ง APK ของนาฬิกาและ APK ของโทรศัพท์ (ไม่บังคับ) ต้องลงชื่อด้วยคีย์เดียวกัน ดูข้อมูลเพิ่มเติมเกี่ยวกับการรวมแพ็กเกจและการลงนามแอป Wear OS ได้ที่ รวมแพ็กเกจและจัดจำหน่ายแอป Wear