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

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

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

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

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

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

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

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

KotlinGroovy
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"
        }
    }
}
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 ในการกำหนดค่าบิลด์ แล้วใส่การตั้งค่าที่ต้องการ ผลิตภัณฑ์ย่อยรองรับพร็อพเพอร์ตี้เดียวกับ 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.

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

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

KotlinGroovy
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"
        }
    }
}
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> ตัวอย่างเช่น หากคุณสร้างเวอร์ชันผลิตภัณฑ์ "สาธิต" และ "เวอร์ชันเต็มรูปแบบ" และเก็บประเภทบิลด์ "แก้ไขข้อบกพร่อง" และ "รุ่น" ไว้ตามค่าเริ่มต้น Gradle จะสร้างตัวแปรบิลด์ต่อไปนี้

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

KotlinGroovy
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"
      ...
    }
  }
}
...
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 จะใช้แหล่งที่มาเหล่านั้นเฉพาะเมื่อสร้างตัวแปรที่รวม Flavour ผลิตภัณฑ์ 2 รายการดังกล่าว

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

กรองตัวแปร

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

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

KotlinGroovy
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
        }
    }
}
...
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/ชุดซอร์สโค้ด และใช้ชุดซอร์สโค้ดของตัวแปรผลิตภัณฑ์เพื่อเปลี่ยนการสร้างแบรนด์ของแอปสําหรับลูกค้ารายต่างๆ หรือรวมสิทธิ์พิเศษและฟังก์ชันการบันทึกสําหรับตัวแปรบิลด์ที่ใช้ประเภทบิลด์แก้ไขข้อบกพร่องเท่านั้น

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

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

------------------------------------------------------------
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/ สำหรับประเภทบิลด์ "แก้ไขข้อบกพร่อง" ให้ทำดังนี้

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

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

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

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

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

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

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

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

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

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

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

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

KotlinGroovy
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")
      ...
  }
}
...
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" ซึ่งเป็นเวอร์ชันข้ามผลิตภัณฑ์ของเวอร์ชันผลิตภัณฑ์ "สาธิต" และประเภทบิลด์ "แก้ไขข้อบกพร่อง" Gradle จะดูไดเรกทอรีเหล่านี้และให้ลำดับความสำคัญดังต่อไปนี้

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

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

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

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

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

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

  • ระบบจะผสานไฟล์ Manifest เข้าด้วยกันเป็นไฟล์เดียว โดยระบบจะจัดลําดับความสําคัญตามลําดับเดียวกับรายการในตัวอย่างก่อนหน้า กล่าวคือ การตั้งค่าไฟล์ Manifest สําหรับประเภทบิลด์จะลบล้างการตั้งค่าไฟล์ Manifest สําหรับตัวแปรผลิตภัณฑ์ และอื่นๆ ดูข้อมูลเพิ่มเติมเกี่ยวกับการผสานไฟล์ Manifest
  • ระบบจะผสานไฟล์ในไดเรกทอรี values/ เข้าด้วยกัน หากไฟล์ 2 ไฟล์มีชื่อเดียวกัน เช่น ไฟล์ strings.xml 2 ไฟล์ ระบบจะจัดลําดับความสําคัญตามลําดับเดียวกับรายการในตัวอย่างก่อนหน้านี้ กล่าวคือ ค่าที่กําหนดไว้ในไฟล์ในชุดแหล่งที่มาของประเภทบิลด์จะลบล้างค่าที่กําหนดไว้ในไฟล์เดียวกันในตัวแปรผลิตภัณฑ์ และอื่นๆ
  • ทรัพยากรในไดเรกทอรี 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")
}
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 ขึ้นไปมีกลไก Dependency ใหม่ที่จับคู่ตัวแปรโดยอัตโนมัติเมื่อใช้ไลบรารี ซึ่งหมายความว่าตัวแปร debug ของแอปจะใช้ตัวแปร debug ของไลบรารี และอื่นๆ โดยอัตโนมัติ นอกจากนี้ ยังใช้งานได้เมื่อใช้ตัวแปรต่างๆ ด้วย โดยตัวแปร freeDebug ของแอปจะใช้ตัวแปร freeDebug ของไลบรารี

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

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

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

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

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

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

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

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

    โปรดทราบว่าจะไม่มีปัญหาเมื่อทรัพยากร 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")
            }
        }
    }
    // 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']
            }
        }
    }
  • สำหรับมิติข้อมูล Flavor ที่ระบุซึ่งมีอยู่ในทั้งแอปและทรัพยากร Dependency ของไลบรารี แอปของคุณมี Flavor ที่ไลบรารีไม่มี

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

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

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

    KotlinGroovy
    // 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")
            }
        }
    }
    // 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 ของไลบรารีมีมิติข้อมูล Flavor ที่แอปของคุณไม่มี

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

    โปรดทราบว่าจะไม่มีปัญหาเมื่อแอปมีมิติข้อมูลเวอร์ชันซึ่งทรัพยากร Dependency ของไลบรารีไม่มี เนื่องจากปลั๊กอินจะจับคู่กับมิติข้อมูลที่มีอยู่ในข้อกําหนดเท่านั้น ตัวอย่างเช่น หากทรัพยากร Dependency ไม่มีมิติข้อมูลสำหรับ ABI แอปเวอร์ชัน "freeX86Debug" จะใช้ทรัพยากร Dependency เวอร์ชัน "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") {}
        }
    }
    // 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 ของบิลด์รุ่น เว้นแต่คุณจะกำหนดค่าการรับรองสำหรับบิลด์นี้อย่างชัดเจน หากยังไม่มีคีย์ Signing ให้สร้างคีย์การอัปโหลดและคีย์สโตร์โดยใช้ Android Studio

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

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

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

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

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

KotlinGroovy
storePassword = System.getenv("KSTOREPWD")
keyPassword = System.getenv("KEYPWD")
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