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

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

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

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

ตัวอย่างเช่น Product Flavor "demo" อาจระบุฟีเจอร์บางอย่าง และข้อกำหนดของอุปกรณ์ เช่น ซอร์สโค้ด ทรัพยากร และระดับ API ขั้นต่ำ ในขณะที่ Build Type "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.

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

ตัวอย่างโค้ดต่อไปนี้สร้างมิติข้อมูลรสชาติชื่อ "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 แล้วเลือก New > Directory
  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

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

    เช่น แอปของคุณมีประเภทบิลด์ "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