پیکربندی گونه‌های ساخت

این صفحه به شما نشان می‌دهد که چگونه می‌توانید تنوع ساخت را پیکربندی کنید تا نسخه‌های مختلفی از برنامه‌تان را از یک پروژه واحد ایجاد کنید و چگونه وابستگی‌ها و پیکربندی‌های امضا را به‌درستی مدیریت کنید.

هر تنوع ساخت نشان‌دهنده نسخه متفاوتی از برنامه شما است که می‌توانید بسازید. برای مثال، ممکن است بخواهید یک نسخه از برنامه‌تان را بسازید که رایگان باشد و مجموعه محدودی از محتوا را ارائه دهد، و نسخه پولی دیگری بسازید که محتوای بیشتری را شامل شود. همچنین می‌توانید نسخه‌های مختلفی از برنامه‌تان بسازید که دستگاه‌های مختلفی را براساس سطح میانای برنامه‌سازی کاربردی یا سایر تفاوت‌های دستگاه هدف قرار می‌دهند.

تنوع‌های ساخت نتیجه استفاده Gradle از مجموعه خاصی از قوانین برای ترکیب تنظیمات، کد، و منابع پیکربندی‌شده در انواع ساخت و نسخه‌های ویژه محصول شما است. اگرچه تنوع‌های ساخت را مستقیماً پیکربندی نمی‌کنید، اما انواع ساخت و نسخه‌های ویژه محصول را که آن‌ها را تشکیل می‌دهند پیکربندی می‌کنید.

برای مثال، یک نسخه ویژه محصول «نمونه» ممکن است ویژگی‌های خاص و الزامات دستگاه را مشخص کند، مانند کد منبع سفارشی، منابع، و حداقل سطوح API، درحالی‌که نوع ساخت «اشکال‌زدایی» تنظیمات ساخت و بسته‌بندی متفاوتی را اعمال می‌کند، مانند گزینه‌های اشکال‌زدایی و کلیدهای امضا. تنوع ساخت که این دو را ترکیب می‌کند نسخه «demoDebug» برنامه شما است و شامل ترکیبی از پیکربندی‌ها و منابع موجود در نسخه ویژه محصول «demo»، نوع ساخت «debug»، و مجموعه منبع main/ است.

پیکربندی انواع ساخت

می‌توانید انواع ساخت را در بلوک android فایل build.gradle.kts در سطح ماژول ایجاد و پیکربندی کنید. وقتی ماژول جدیدی ایجاد می‌کنید، Android Studio به‌طور خودکار انواع ساخت اشکال‌زدایی و انتشار را ایجاد می‌کند. اگرچه نوع ساخت اشکال‌زدایی در فایل پیکربندی ساخت نشان داده نمی‌شود، «استودیو Android» آن را با debuggable true پیکربندی می‌کند. این کار به شما امکان می‌دهد برنامه را در دستگاه‌های Android امن اشکال‌زدایی کنید و امضای برنامه را با یک keystore اشکال‌زدایی عمومی پیکربندی کنید.

اگر می‌خواهید تنظیمات خاصی را اضافه یا تغییر دهید، می‌توانید نوع ساخت اشکال‌زدایی را به پیکربندی‌تان اضافه کنید. نمونه زیر یک applicationIdSuffix را برای نوع ساخت اشکال‌زدایی مشخص می‌کند و یک نوع ساخت «مرحله‌ای» را پیکربندی می‌کند که بااستفاده از تنظیمات نوع ساخت اشکال‌زدایی مقداردهی اولیه می‌شود:

کاتلین

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» از شما می‌خواهد پروژه‌تان را با پیکربندی جدید همگام‌سازی کنید. برای همگام‌سازی پروژه، روی اکنون همگام‌سازی شود در نوار اعلان که هنگام ایجاد تغییر ظاهر می‌شود کلیک کنید یا روی همگام‌سازی پروژه در نوارابزار کلیک کنید. اگر Android Studio متوجه خطایی در پیکربندی شما شود، پنجره پیام‌ها برای شرح مشکل ظاهر می‌شود.

برای کسب اطلاعات بیشتر درباره همه ویژگی‌هایی که می‌توانید با انواع ساخت پیکربندی کنید، مرجع BuildType را بخوانید.

پیکربندی نسخه‌های ویژه محصول

ایجاد نسخه‌های ویژه محصول مشابه ایجاد انواع ساخت است. نسخه‌های ویژه محصول را به بلوک productFlavors در پیکربندی ساخت اضافه کنید و تنظیمات موردنظرتان را لحاظ کنید. نسخه‌های ویژه محصول از همان ویژگی‌های defaultConfig پشتیبانی می‌کنند، زیرا defaultConfig درواقع به کلاس ProductFlavor تعلق دارد. این یعنی می‌توانید پیکربندی پایه را برای همه نسخه‌ها در بلوک defaultConfig ارائه دهید و هر نسخه می‌تواند هرکدام از این مقادیر پیش‌فرض را تغییر دهد، مثلاً applicationId. برای کسب اطلاعات بیشتر درباره شناسه برنامه، تنظیم شناسه برنامه را بخوانید.

توجه: همچنان باید نام بسته را بااستفاده از مشخصه package در فایل مانیفست 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 به‌طور خودکار همه طعم‌های پیمانه را به آن پیمانه اختصاص می‌دهد.

نمونه کد زیر یک پیمانه طعم به‌نام «نسخه» ایجاد می‌کند و نسخه‌های ویژه محصول «نمونه نمایشی» و «کامل» را اضافه می‌کند. این طعم‌ها applicationIdSuffix و versionNameSuffix خودشان را ارائه می‌دهند:

کاتلین

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"
        }
    }
}

توجه: اگر برنامه قدیمی‌ای دارید (که قبل‌از اوت ۲۰۲۱ ایجاد شده است) و آن را بااستفاده از 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» نشان داده شوند، مثلاً نسخه «رایگان» و «حرفه‌ای»، باید انواع ساخت جداگانه‌ای ایجاد کنید که هرکدام شناسه برنامه متفاوتی داشته باشند.

در این حالت، هر تنوع ساخت را به‌عنوان یک نسخه ویژه محصول جداگانه تعریف کنید. برای هر طعم در بلوک productFlavors، می‌توانید ویژگی applicationId را بازتعریف کنید، یا می‌توانید به‌جای آن، بااستفاده از applicationIdSuffix، بخشی را به شناسه برنامه پیش‌فرض اضافه کنید، همان‌طور که در اینجا نشان داده شده است:

کاتلین

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 برای افزودن بخش براساس نوع ساخت خود استفاده کنید، همان‌طور که در اینجا نشان داده شده است:

کاتلین

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

شیک

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

چون Gradle پیکربندی نوع ساخت را بعداز نسخه ویژه محصول اعمال می‌کند، شناسه برنامه برای تنوع ساخت «اشکال‌زدایی رایگان» «com.example.myapp.free.debug» است. این زمانی مفید است که می‌خواهید هم ساخت اشکال‌زدایی و هم ساخت نسخه پخش را در یک دستگاه داشته باشید، زیرا هیچ دو برنامه‌ای نمی‌توانند شناسه برنامه یکسانی داشته باشند.

اگر برنامه قدیمی‌ای دارید (که قبل‌از اوت ۲۰۲۱ ایجاد شده است) و آن را بااستفاده از APK در Google Play توزیع می‌کنید، و می‌خواهید از همان فهرستگان برنامه برای توزیع چند APK استفاده کنید که هرکدام پیکربندی دستگاه متفاوتی را هدف قرار می‌دهند (مثلاً سطح API)، باید از شناسه برنامه یکسانی برای هر تنوع ساخت استفاده کنید اما به هر APK یک versionCode متفاوت اختصاص دهید. برای اطلاعات بیشتر، درباره پشتیبانی از چند APK بخوانید. انتشار بااستفاده از AAB تحت‌تأثیر قرار نمی‌گیرد، زیرا از یک آرتیفکت واحد استفاده می‌کند که به‌طور پیش‌فرض از یک کد نسخه و شناسه برنامه واحد استفاده می‌کند.

نکته: اگر لازم است به شناسه برنامه در فایل مانیفست خود ارجاع دهید، می‌توانید از جای‌بان ${applicationId} در هر ویژگی مانیفست استفاده کنید. درطول ساخت، Gradle این برچسب را با شناسه واقعی برنامه جایگزین می‌کند. برای اطلاعات بیشتر، تزریق متغیرهای ساخت به مانیفست را ببینید.

ترکیب کردن چند نسخه ویژه محصول با پیمانه‌های طعم

در برخی موارد، ممکن است بخواهید پیکربندی‌های چند نسخه ویژه محصول را ترکیب کنید. برای مثال، ممکن است بخواهید پیکربندی‌های متفاوتی برای نسخه‌های ویژه محصول «کامل» و «نمونه نمایشی» که براساس سطح میانای برنامه‌سازی کاربردی هستند ایجاد کنید. برای انجام این کار، افزایه Android Gradle به شما امکان می‌دهد چندین گروه از نسخه‌های ویژه محصول را به‌عنوان پیمانه‌های طعم ایجاد کنید.

هنگام ساختن برنامه، Gradle پیکربندی نسخه ویژه محصول را از هر پیمانه طعمی که تعریف می‌کنید، همراه با پیکربندی نوع ساخت، ترکیب می‌کند تا تنوع ساخت نهایی را ایجاد کند. Gradle نسخه‌های ویژه محصول را که به یک پیمانه طعم تعلق دارند ترکیب نمی‌کند.

نمونه کد زیر از ویژگی flavorDimensions برای ایجاد پیمانه طعم «حالت» برای گروه‌بندی نسخه‌های ویژه محصول «کامل» و «نمونه» و پیمانه طعم «api» برای گروه‌بندی پیکربندی‌های نسخه ویژه محصول براساس سطح API استفاده می‌کند:

کاتلین

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 درمجموع ۱۲ تنوع ساخت با طرح نام‌گذاری زیر ایجاد می‌کند:

  • تنوع ساخت: [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 فقط هنگام ساختن متغیری که آن دو نسخه ویژه محصول را ترکیب می‌کند از آن منابع استفاده می‌کند.

مجموعه‌های منبعی که برای ترکیب‌های نسخه ویژه محصول ایجاد می‌کنید اولویت بالاتری نسبت‌به مجموعه‌های منبعی دارند که به هر نسخه ویژه محصول به‌طور جداگانه تعلق دارند. برای کسب اطلاعات بیشتر درباره مجموعه‌های منبع و نحوه ادغام منابع توسط Gradle، بخش مربوط به نحوه ایجاد مجموعه‌های منبع را بخوانید.

فیلتر کردن گونه‌ها

Gradle برای هر ترکیب ممکن از نسخه‌های ویژه محصول و انواع ساختی که پیکربندی می‌کنید، یک تنوع ساخت ایجاد می‌کند. بااین‌حال، ممکن است برخی‌از تنوع‌های ساخت وجود داشته باشند که به آن‌ها نیاز ندارید یا در بافت پروژه شما منطقی نیستند. برای برداشتن پیکربندی‌های تنوع ساخت خاص، فیلتر تنوعی در فایل build.gradle.kts سطح واحدتان ایجاد کنید.

بااستفاده از پیکربندی ساخت از بخش قبلی به‌عنوان نمونه، فرض کنید قصد دارید فقط از سطح ای‌پی‌آی ۲۳ و بالاتر برای نسخه نمایشی برنامه پشتیبانی کنید. می‌توانید از بلوک variantFilter برای فیلتر کردن همه پیکربندی‌های تنوع ساخت که نسخه‌های ویژه محصول «minApi21» و «demo» را ترکیب می‌کنند استفاده کنید:

کاتلین

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. روی File (فایل) > Settings (تنظیمات) > Experimental (آزمایشی) (Android Studio > Settings (تنظیمات) > Experimental (آزمایشی) در macOS) کلیک کنید.
    2. Do not build Gradle task list during Gradle sync (فهرست تکلیف Gradle درطول همگام‌سازی Gradle ساخته نشود) را لغو انتخاب کنید.
  3. پس‌از اینکه Gradle تکلیف را اجرا کرد، پنجره اجرا باز می‌شود تا برونداد را نمایش دهد.

توجه: خروجی تکلیف همچنین به شما نشان می‌دهد که چگونه مجموعه‌های منبع را برای فایل‌هایی که می‌خواهید برای اجرای آزمایش‌های برنامه‌تان استفاده کنید، مانند test/ و androidTest/ مجموعه‌های منبع آزمایشی، سازماندهی کنید.

وقتی تنوع ساخت جدیدی ایجاد می‌کنید، Android Studio دایرکتوری‌های مجموعه منبع را برای شما ایجاد نمی‌کند، اما چند گزینه برای کمک به شما ارائه می‌دهد. برای مثال، برای ایجاد فقط دایرکتوری java/ برای نوع ساخت «اشکال‌زدایی»:

  1. قاب پروژه را باز کنید و نمای پروژه را از منو بالای قاب انتخاب کنید.
  2. به MyProject/app/src/ پیمایش کنید.
  3. روی پوشه src کلیک راست کنید و جدید > پوشه را انتخاب کنید.
  4. از منوِ زیر مجموعه‌های منبع Gradle، full/java را انتخاب کنید.
  5. کلید Enter را فشار دهید.

Android Studio دایرکتوری مجموعه منبعی برای نوع ساخت اشکال‌زدایی شما ایجاد می‌کند و سپس دایرکتوری java/ را در آن ایجاد می‌کند. یا اینکه وقتی فایل جدیدی را برای تنوع ساخت خاصی به پروژه‌تان اضافه می‌کنید، Android Studio می‌تواند دایرکتوری‌ها را برایتان ایجاد کند.

برای مثال، برای ایجاد فایل XML مقادیر برای نوع ساخت «اشکال‌زدایی»:

  1. در صفحه پروژه، روی دایرکتوری src کلیک راست کنید و جدید > XML > فایل XML مقادیر را انتخاب کنید.
  2. نام فایل XML را وارد کنید یا نام پیش‌فرض را نگه دارید.
  3. از منوِ کنار مجموعه منبع هدف، اشکال‌زدایی را انتخاب کنید.
  4. روی پایان کلیک کنید.

چون نوع ساخت «اشکال‌زدایی» به‌عنوان مجموعه منبع هدف مشخص شده است، Android Studio به‌طور خودکار دایرکتوری‌های لازم را هنگام ایجاد فایل XML ایجاد می‌کند. ساختار دایرکتوری حاصل مانند شکل ۱ است.

شکل ۱. دایرکتوری‌های مجموعه منبع جدید برای نوع ساخت «اشکال‌زدایی».

مجموعه‌های منبع فعال نشانگر سبزی در نمادشان دارند که نشان می‌دهد فعال هستند. مجموعه منبع debug با پسوند [main] نشان داده می‌شود تا مشخص شود که در مجموعه منبع main ادغام خواهد شد.

بااستفاده از همین روش، می‌توانید دایرکتوری‌های مجموعه منبع را برای نسخه‌های ویژه محصول، مثل src/demo/، و تنوع‌های ساخت، مثل src/demoDebug/، نیز ایجاد کنید. علاوه‌براین، می‌توانید مجموعه‌های منبع آزمایشی ایجاد کنید که تنوع‌های ساخت خاصی را هدف قرار می‌دهند، مانند src/androidTestDemoDebug/. برای کسب اطلاعات بیشتر، درباره مجموعه‌های منبع آزمایشی بخوانید.

تغییر پیکربندی‌های مجموعه منبع پیش‌فرض

اگر منابعی دارید که در ساختار فایل مجموعه منبع پیش‌فرضی که Gradle انتظار دارد سازمان‌دهی نشده‌اند، همان‌طور که در بخش قبلی درباره ایجاد مجموعه‌های منبع توضیح داده شد، می‌توانید از بلوک sourceSets برای تغییر جایی که Gradle برای جمع‌آوری فایل‌ها برای هر مؤلفه از مجموعه منبع جستجو می‌کند استفاده کنید.

بلوک sourceSets باید در بلوک android باشد. نیازی نیست فایل‌های منبع را جابه‌جا کنید؛ فقط باید مسیر(های) مربوط به فایل build.gradle.kts در سطح ماژول را که Gradle می‌تواند فایل‌های هر مؤلفه مجموعه منبع را در آن پیدا کند به Gradle ارائه دهید. برای اینکه بدانید کدام مؤلفه‌ها را می‌توانید پیکربندی کنید و آیا می‌توانید آن‌ها را به چندین فایل یا دایرکتوری نگاشت کنید، به مرجع میانای برنامه‌سازی کاربردی افزایه Android Gradle مراجعه کنید.

نمونه کد زیر منابع را از دایرکتوری app/other/ به مؤلفه‌های خاصی از مجموعه منبع main نگاشت می‌کند و دایرکتوری ریشه مجموعه منبع androidTest را تغییر می‌دهد:

کاتلین

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» هستید که محصول متقاطع نسخه ویژه محصول «demo» و نوع ساخت «debug» است، Gradle این دایرکتوری‌ها را بررسی می‌کند و اولویت زیر را به آن‌ها می‌دهد:

  1. ‫src/demoDebug/ (مجموعه منبع تنوع ساخت)
  2. ‫src/debug/ (مجموعه منبع نوع ساخت)
  3. src/demo/ (مجموعه منبع نسخه ویژه محصول)
  4. ‫src/main/ (مجموعه منبع اصلی)

مجموعه‌های منبع ایجادشده برای ترکیب‌های نسخه‌های ویژه محصول باید شامل همه پیمانه‌های طعم باشد. برای مثال، مجموعه منبع تنوع ساخت باید ترکیبی از نوع ساخت و همه پیمانه‌های طعم باشد. ادغام کد و منابع شامل پوشه‌هایی که چند پیمانه طعم را پوشش می‌دهند اما نه همه آن‌ها را، پشتیبانی نمی‌شود.

اگر چند نسخه ویژه محصول را ترکیب کنید، اولویت بین نسخه‌های ویژه محصول براساس پیمانه طعمی که به آن تعلق دارند تعیین می‌شود. هنگام فهرست کردن پیمانه‌های طعم با ویژگی android.flavorDimensions، نسخه‌های ویژه محصول به‌ترتیب اعلام پیمانه‌هایشان اولویت‌بندی می‌شوند، به‌طوری‌که پیمانه‌های قبلی بر پیمانه‌های بعدی اولویت دارند. علاوه‌براین، مجموعه‌های منبعی که برای ترکیبی از نسخه‌های ویژه محصول ایجاد می‌کنید اولویت بالاتری نسبت‌به مجموعه‌های منبعی دارند که به یک نسخه ویژه محصول تعلق دارند.

ترتیب اولویت تعیین می‌کند که وقتی Gradle کد و منابع را ترکیب می‌کند، کدام مجموعه منبع اولویت بالاتری دارد. چون دایرکتوری مجموعه منبع demoDebug/ احتمالاً حاوی فایل‌هایی است که مختص آن تنوع ساخت است، اگر demoDebug/ شامل فایلی باشد که در debug/ نیز تعریف شده است، Gradle از فایل موجود در مجموعه منبع demoDebug/ استفاده می‌کند. به‌طور مشابه، Gradle به فایل‌های موجود در نوع ساخت و مجموعه منبع نسخه ویژه محصول اولویت بالاتری نسبت‌به همان فایل‌ها در main/ می‌دهد. Gradle هنگام اعمال قوانین ساخت زیر، این ترتیب اولویت را درنظر می‌گیرد:

  • همه کدهای منبع در دایرکتوری‌های kotlin/ یا java/ با هم کامپایل می‌شوند تا یک خروجی واحد تولید شود.

    توجه: برای یک تنوع ساخت مشخص، اگر Gradle با دو یا چند دایرکتوری مجموعه منبع مواجه شود که کلاس Kotlin یا Java یکسانی را تعریف کرده‌اند، خطای ساخت ایجاد می‌کند. برای مثال، هنگام ساختن برنامه اشکال‌زدایی، نمی‌توانید هم src/debug/Utility.kt و هم src/main/Utility.kt را تعریف کنید، زیرا Gradle درطول فرایند ساختن به هر دو این دایرکتوری‌ها نگاه می‌کند و خطای «کلاس تکراری» می‌دهد. اگر نسخه‌های مختلفی از Utility.kt را برای انواع مختلف ساخت می‌خواهید، هر نوع ساخت باید نسخه خودش را از فایل تعریف کند و آن را در مجموعه منبع main/ قرار ندهد.

  • مانیفست‌ها با هم ادغام می‌شوند و یک مانیفست واحد را تشکیل می‌دهند. اولویت به همان ترتیبی که در فهرست مثال قبلی آمده است داده می‌شود. برای مثال، تنظیمات مانیفست برای نوع ساخت، تنظیمات مانیفست را برای نسخه ویژه محصول لغو می‌کند. برای کسب اطلاعات بیشتر، درباره ادغام مانیفست بخوانید.
  • فایل‌های موجود در دایرکتوری‌های values/ با یکدیگر ادغام می‌شوند. اگر دو فایل نام یکسانی داشته باشند، مثلاً دو فایل strings.xml، اولویت به همان ترتیبی است که در فهرست مثال قبلی آمده است. برای مثال، مقادیر تعریف‌شده در فایلی در مجموعه منبع نوع ساخت، مقادیر تعریف‌شده در همان فایل را در نسخه ویژه محصول لغو می‌کند.
  • منابع موجود در دایرکتوری‌های res/ و asset/ باهم بسته‌بندی شده‌اند. اگر منابعی با نام یکسان در دو یا چند مجموعه منبع تعریف شده باشند، اولویت به همان ترتیبی که در فهرست مثال قبلی آمده است داده می‌شود.
  • Gradle به منابع و مانیفست‌های موجود در وابستگی‌های ماژول کتابخانه، پایین‌ترین اولویت را هنگام ساخت برنامه می‌دهد.

اعلام وابستگی‌ها

برای پیکربندی وابستگی برای یک تنوع ساخت خاص یا مجموعه منبع آزمایشی، نام تنوع ساخت یا مجموعه منبع آزمایشی را قبل‌از کلیدواژه Implementation پیشوند کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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 نسخه ۳.۰.۰ و بالاتر شامل سازوکار وابستگی جدیدی است که به‌طور خودکار انواع را هنگام استفاده از کتابخانه مطابقت می‌دهد. برای مثال، متغیر debug برنامه به‌طور خودکار متغیر debug کتابخانه را مصرف می‌کند. این ویژگی هنگام استفاده از طعم‌ها نیز کار می‌کند: نوع freeDebug برنامه، نوع freeDebug کتابخانه را مصرف خواهد کرد.

برای اینکه افزونه بتواند انواع را به‌طور دقیق مطابقت دهد، باید جایگزین‌های منطبق ارائه دهید، همان‌طور که در بخش زیر توضیح داده شده است، برای مواردی که مطابقت مستقیم امکان‌پذیر نیست.

برای مثال، فرض کنید برنامه‌تان نوع ساختاری به‌نام «staging» را پیکربندی می‌کند، اما یکی از وابستگی‌های کتابخانه‌اش این کار را نمی‌کند. وقتی افزونه تلاش می‌کند نسخه «مرحله‌ای» برنامه‌تان را بسازد، نمی‌داند از کدام نسخه کتابخانه استفاده کند و پیام خطایی مشابه پیام زیر خواهید دید:

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

رفع خطاهای ساخت مربوط به مطابقت دادن گونا‌ها

این افزونه شامل عناصر DSL است تا به شما کمک کند نحوه حل‌وفصل موقعیت‌هایی را که در آن تطابق مستقیم گونه بین برنامه و وابستگی ممکن نیست توسط Gradle کنترل کنید.

در زیر فهرستی از مشکلات مربوط به تطابق وابستگی آگاه از گونه و نحوه حل آن‌ها بااستفاده از ویژگی‌های DSL ارائه شده است:

  • برنامه شما شامل نوع ساختی است که وابستگی کتابخانه ندارد.

    برای مثال، برنامه شما شامل نوع ساخت «مرحله‌ای» است، اما وابستگی فقط شامل انواع ساخت «اشکال‌زدایی» و «انتشار» است.

    توجه داشته باشید که اگر وابستگی کتابخانه شامل نوع ساختی باشد که برنامه شما ندارد، مشکلی وجود ندارد. دلیلش این است که افزونه هرگز آن نوع ساخت را از وابستگی درخواست نمی‌کند.

    از matchingFallbacks برای مشخص کردن مطابقت‌های جایگزین برای نوع ساخت داده‌شده استفاده کنید، همان‌طور که در اینجا نشان داده شده است:

    کاتلین

    // 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']
            }
        }
    }
  • برای پیمانه طعم معینی که هم در برنامه و هم در وابستگی کتابخانه آن وجود دارد، برنامه شما شامل طعم‌هایی است که کتابخانه ندارد.

    برای مثال، هم برنامه شما و هم وابستگی‌های کتابخانه آن شامل پیمانه طعم «ردیف» است. بااین‌حال، بُعد «سطح» در برنامه شامل طعم‌های «رایگان» و «پولی» است، اما یک وابستگی فقط شامل طعم‌های «نمونه» و «پولی» برای همان بُعد است.

    توجه داشته باشید که برای یک پیمانه طعم معین که هم در برنامه و هم در وابستگی‌های کتابخانه آن وجود دارد، وقتی کتابخانه شامل نسخه ویژه محصولی باشد که برنامه شما ندارد، مشکلی وجود ندارد. دلیلش این است که افزونه هرگز آن نوع را از وابستگی درخواست نمی‌کند.

    از matchingFallbacks برای مشخص کردن مطابقت‌های جایگزین برای نسخه ویژه محصول «رایگان» برنامه استفاده کنید، همان‌طور که در اینجا نشان داده شده است:

    کاتلین

    // 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']
            }
        }
    }
  • وابستگی کتابخانه شامل پیمانه طعمی است که برنامه شما ندارد.

    برای مثال، وابستگی کتابخانه شامل طعم‌هایی برای بُعد «minApi» است، اما برنامه شما فقط شامل طعم‌هایی برای بُعد «tier» است. وقتی می‌خواهید نسخه «freeDebug» برنامه‌تان را بسازید، افزونه نمی‌داند که باید از نسخه «minApi23Debug» یا «minApi18Debug» وابستگی استفاده کند.

    توجه داشته باشید که اگر برنامه‌تان شامل پیمانه طعمی باشد که وابستگی کتابخانه ندارد، مشکلی وجود ندارد. دلیلش این است که افزونه فقط با انواع ابعادی مطابقت دارد که در وابستگی وجود دارند. برای مثال، اگر وابستگی شامل بُعدی برای ABI نباشد، نسخه «freeX86Debug» برنامه‌تان از نسخه «freeDebug» وابستگی استفاده می‌کند.

    از missingDimensionStrategy در بلوک defaultConfig برای مشخص کردن طعم پیش‌فرض برای افزونه استفاده کنید تا از هر بُعد گم‌شده انتخاب کند، همان‌طور که در نمونه زیر نشان داده شده است. همچنین می‌توانید انتخاب‌هایتان را در بلوک productFlavors لغو کنید تا هر نسخه بتواند استراتژی تطابق متفاوتی را برای بُعد مفقود مشخص کند.

    کاتلین

    // 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 ساخت نسخهٔ پخش شما را امضا نمی‌کند، مگراینکه به‌طور صریح پیکربندی امضا را برای این ساخت تعریف کنید. اگر هنوز کلید امضا ندارید، بااستفاده از Android Studio کلید بارگذاری و keystore تولید کنید.

برای پیکربندی دستی پیکربندی‌های امضا برای نوع ساخت نسخه پخش بااستفاده از پیکربندی‌های ساخت Gradle:

  1. یک keystore ایجاد کنید. مخزن کلید فایل دودویی است که حاوی مجموعه‌ای از کلیدهای خصوصی است. باید keystore خود را در مکانی امن و مطمئن نگهداری کنید.
  2. کلید خصوصی ایجاد کنید. از کلید خصوصی برای امضا کردن برنامه شما جهت توزیع استفاده می‌شود و هرگز در برنامه گنجانده نمی‌شود یا برای اشخاص ثالث غیرمجاز فاش نمی‌شود.
  3. پیکربندی امضا را به فایل build.gradle.kts در سطح ماژول اضافه کنید:

    کاتلین

    ...
    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
            }
        }
    }

توجه: گنجاندن گذرواژه‌های کلید انتشار و مخزن کلید در فایل ساخت، روش امنیتی خوبی نیست. به‌جای آن، فایل ساخت را پیکربندی کنید تا این گذرواژه‌ها را از متغیرهای محیطی دریافت کند یا فرایند ساخت از شما بخواهد این گذرواژه‌ها را وارد کنید.

برای دریافت این گذرواژه‌ها از متغیرهای محیطی:

کاتلین

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

شیک

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

یا می‌توانید keystore را از فایل ویژگی‌های محلی بار کنید. به‌دلایل امنیتی، این فایل را به کنترل منبع اضافه نکنید. به‌جای آن، آن را به‌صورت محلی برای هر توسعه‌دهنده راه‌اندازی کنید. برای کسب اطلاعات بیشتر، برداشتن اطلاعات امضا از فایل‌های ساخت را بخوانید.

پس‌از تکمیل این فرایند، می‌توانید برنامه‌تان را توزیع و آن را در Google Play منتشر کنید.

هشدار: keystore و کلید خصوصی‌تان را در مکانی امن و مطمئن نگه دارید و مطمئن شوید که نسخه‌های پشتیبان امنی از آن‌ها دارید. اگر از «امضای برنامه» Play استفاده می‌کنید و کلید بارگذاری‌تان را گم کرده‌اید، می‌توانید بااستفاده از «کنسول Play» درخواست بازنشانی بدهید. اگر برنامه‌ای را بدون «امضای برنامه Play» منتشر می‌کنید (برای برنامه‌هایی که قبل‌از اوت ۲۰۲۱ ایجاد شده‌اند) و کلید امضای برنامه‌تان را گم کنید، نمی‌توانید هیچ به‌روزرسانی‌ای برای برنامه‌تان منتشر کنید، زیرا همیشه باید همه نسخه‌های برنامه‌تان را با همان کلید امضا کنید.

امضا کردن برنامه‌های Wear OS

هنگام انتشار برنامه‌های Wear OS، هم APK ساعت و هم APK اختیاری تلفن باید با کلید یکسانی امضا شده باشند. برای اطلاعات بیشتر درباره بسته‌بندی و امضای برنامه‌های Wear OS، بسته‌بندی و توزیع برنامه‌های Wear را ببینید.