বিল্ড ভ্যারিয়েন্ট কনফিগার করুন

এই পৃষ্ঠা থেকে আপনি জানতে পারবেন যে কীভাবে বিল্ড ভ্যারিয়েন্ট কনফিগার করে একটি প্রোজেক্ট থেকে আপনার অ্যাপের বিভিন্ন ভার্সন তৈরি করতে পারবেন এবং কীভাবে আপনার ডিপেন্ডেন্সি ও সাইনিং কনফিগারেশন সঠিকভাবে ম্যানেজ করতে পারবেন।

প্রতিটি বিল্ড ভ্যারিয়েন্ট আপনার অ্যাপের একটি আলাদা ভার্সন দেখায় যা আপনি তৈরি করতে পারবেন। যেমন, আপনি হয়ত আপনার অ্যাপের একটি ভার্সন তৈরি করতে চান যা সীমিত কন্টেন্ট সহ ফ্রি এবং আরেকটি পেড ভার্সন যাতে আরও বেশি কন্টেন্ট থাকবে। এছাড়াও, আপনি API লেভেল বা অন্যান্য ডিভাইসের ভ্যারিয়েশনের উপর ভিত্তি করে বিভিন্ন ডিভাইসকে টার্গেট করে আপনার অ্যাপের বিভিন্ন ভার্সন তৈরি করতে পারেন।

বিল্ড ভেরিয়েন্ট হল Gradle-এর ফলাফল যা আপনার বিল্ডের ধরন ও প্রোডাক্ট ফ্লেভারে কনফিগার করা সেটিংস, কোড ও রিসোর্স একত্রিত করার জন্য নিয়মের নির্দিষ্ট সেট ব্যবহার করে। যদিও আপনি সরাসরি বিল্ড ভেরিয়েন্ট কনফিগার করেন না, আপনি বিল্ডের ধরন এবং প্রোডাক্ট ফ্লেভার কনফিগার করেন যা সেগুলি তৈরি করে।

যেমন, "ডেমো" প্রোডাক্ট ফ্লেভার নির্দিষ্ট কিছু ফিচার ও ডিভাইসের প্রয়োজনীয়তা উল্লেখ করতে পারে, যেমন কাস্টম সোর্স কোড, রিসোর্স ও ন্যূনতম API লেভেল, যেখানে "ডিবাগ" বিল্ড টাইপ বিভিন্ন বিল্ড ও প্যাকেজিং সেটিংস প্রয়োগ করে, যেমন ডিবাগ বিকল্প ও সাইনিং কী। এই দুটি একত্রিত করে যে বিল্ড ভ্যারিয়েন্ট তৈরি হয় সেটি হল আপনার অ্যাপের "demoDebug" ভার্সন এবং এতে "demo" প্রোডাক্ট ফ্লেভার, "debug" বিল্ড টাইপ ও main/ সোর্স সেটে অন্তর্ভুক্ত কনফিগারেশন ও রিসোর্সের সমন্বয় থাকে।

বিল্ডের ধরন কনফিগার করুন

আপনি মডিউল-লেভেল build.gradle.kts ফাইলের android ব্লকের মধ্যে বিল্ডের ধরন তৈরি ও কনফিগার করতে পারবেন। আপনি নতুন মডিউল তৈরি করলে, Android Studio অটোমেটিক ডিবাগ ও রিলিজ বিল্ডের ধরন তৈরি করে। যদিও ডিবাগ বিল্ডের ধরন বিল্ড কনফিগারেশন ফাইলে দেখা যায় না, Android Studio এটিকে debuggable true দিয়ে কনফিগার করে। এটি আপনাকে সুরক্ষিত Android ডিভাইসে অ্যাপ ডিবাগ করতে দেয় এবং একটি জেনেরিক ডিবাগ কীস্টোর দিয়ে অ্যাপ সাইনিং কনফিগার করে।

আপনি নির্দিষ্ট কিছু সেটিংস যোগ বা পরিবর্তন করতে চাইলে, আপনার কনফিগারেশনে ডিবাগ বিল্ডের ধরন যোগ করতে পারেন। নিম্নলিখিত স্যাম্পেল ডিবাগ বিল্ড টাইপের জন্য একটি applicationIdSuffix নির্দিষ্ট করে এবং "স্টেজিং" বিল্ড টাইপ কনফিগার করে যা ডিবাগ বিল্ড টাইপ থেকে সেটিংস ব্যবহার করে শুরু করা হয়:

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

গ্ৰুভি

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। অ্যাপ্লিকেশন আইডি সম্পর্কে আরও জানতে, অ্যাপ্লিকেশন আইডি সেট করুন নিবন্ধটি পড়ুন।

মনে রাখবেন: আপনাকে এখনও main/ ম্যানিফেস্ট ফাইলে package অ্যাট্রিবিউট ব্যবহার করে প্যাকেজের নাম উল্লেখ করতে হবে। এছাড়াও, 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 প্রদান করে:

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

গ্ৰুভি

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

মনে রাখবেন: আপনার কাছে যদি কোনও লিগ্যাসি অ্যাপ (আগস্ট ২০২১-এর আগে তৈরি করা) থাকে যা আপনি Google Play-তে APK ব্যবহার করে ডিস্ট্রিবিউট করেন, তাহলে Google Play-তে একাধিক APK সাপোর্ট ব্যবহার করে আপনার অ্যাপ ডিস্ট্রিবিউট করতে, সব ভেরিয়েন্টে একই applicationId ভ্যালু অ্যাসাইন করুন এবং প্রতিটি ভেরিয়েন্টকে আলাদা versionCode দিন। Google Play-তে আপনার অ্যাপের বিভিন্ন ভার্সন আলাদা আলাদা অ্যাপ হিসেবে ডিস্ট্রিবিউট করতে, আপনাকে প্রতিটি ভার্সনের জন্য আলাদা আলাদা applicationId অ্যাসাইন করতে হবে।

আপনার প্রোডাক্ট ফ্লেভার তৈরি ও কনফিগার করার পরে, বিজ্ঞপ্তি বারে এখনই সিঙ্ক করুন বিকল্পে ক্লিক করুন। সিঙ্ক করা সম্পূর্ণ হলে, Gradle আপনার বিল্ডের ধরন ও প্রোডাক্টের ফ্লেভারের উপর ভিত্তি করে অটোমেটিক বিল্ড ভেরিয়েন্ট তৈরি করে এবং <product-flavor><Build-Type> অনুযায়ী সেগুলির নাম দেয়। যেমন, আপনি যদি "ডেমো" এবং "সম্পূর্ণ" প্রোডাক্ট ফ্লেভার তৈরি করেন এবং ডিফল্ট "ডিবাগ" এবং "রিলিজ" বিল্ড টাইপ রাখেন, তাহলে Gradle নিম্নলিখিত বিল্ড ভেরিয়েন্ট তৈরি করে:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

কোন বিল্ড ভেরিয়েন্ট তৈরি ও রান করতে হবে তা বেছে নিতে, বিল্ড > বিল্ড ভেরিয়েন্ট বেছে নিন বিকল্পে যান এবং মেনু থেকে একটি বিল্ড ভেরিয়েন্ট বেছে নিন। প্রতিটি বিল্ড ভেরিয়েন্টকে নিজস্ব ফিচার ও রিসোর্স দিয়ে কাস্টমাইজ করা শুরু করতে, আপনাকে এই পৃষ্ঠায় বর্ণনা করা পদ্ধতি অনুযায়ী সোর্স সেট তৈরি ও ম্যানেজ করতে হবে।

বিল্ড ভ্যারিয়েন্টের জন্য অ্যাপ্লিকেশন আইডি পরিবর্তন করা

আপনার অ্যাপের জন্য APK বা AAB তৈরি করার সময়, বিল্ড টুল অ্যাপটিকে build.gradle.kts ফাইল থেকে defaultConfig ব্লকে উল্লেখ করা অ্যাপ্লিকেশন আইডি দিয়ে ট্যাগ করে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে। তবে, আপনি যদি Google Play Store-এ আলাদা তালিকা হিসেবে দেখানোর জন্য আপনার অ্যাপের বিভিন্ন ভার্সন তৈরি করতে চান, যেমন "ফ্রি" এবং "প্রো" ভার্সন, তাহলে আপনাকে আলাদা বিল্ড ভ্যারিয়েন্ট তৈরি করতে হবে, যার প্রতিটির আলাদা অ্যাপ্লিকেশন আইডি থাকবে।

এই ক্ষেত্রে, প্রতিটি বিল্ড ভেরিয়েন্টকে আলাদা প্রোডাক্ট ফ্লেভার হিসেবে সংজ্ঞায়িত করুন। productFlavors ব্লকের মধ্যে প্রতিটি ফ্লেভারের জন্য, আপনি applicationId প্রপার্টি আবার সংজ্ঞায়িত করতে পারেন, অথবা আপনি applicationIdSuffix ব্যবহার করে ডিফল্ট অ্যাপ্লিকেশন আইডিতে একটি সেগমেন্ট যোগ করতে পারেন, যেমন এখানে দেখানো হয়েছে:

Kotlin

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 ব্যবহার করে আপনার বিল্ডের ধরন-এর উপর ভিত্তি করে একটি সেগমেন্ট যোগ করতে পারেন, যেমন এখানে দেখানো হয়েছে:

Kotlin

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

গ্ৰুভি

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

যেহেতু Gradle প্রোডাক্ট ফ্লেভারের পরে বিল্ড টাইপ কনফিগারেশন প্রয়োগ করে, তাই "ফ্রি ডিবাগ" বিল্ড ভ্যারিয়েন্টের জন্য অ্যাপ্লিকেশন আইডি হল "com.example.myapp.free.debug"। আপনি একই ডিভাইসে ডিবাগ ও রিলিজ বিল্ড, দুটিই রাখতে চাইলে এটি কাজে লাগে, কারণ দুটি অ্যাপের একই অ্যাপ্লিকেশন আইডি থাকতে পারে না।

আপনার যদি কোনও লিগ্যাসি অ্যাপ (আগস্ট ২০২১-এর আগে তৈরি) থাকে যা আপনি Google Play-তে APK ব্যবহার করে ডিস্ট্রিবিউট করেন এবং আপনি একাধিক APK ডিস্ট্রিবিউট করার জন্য একই অ্যাপ তালিকা ব্যবহার করতে চান, যার প্রতিটি আলাদা ডিভাইস কনফিগারেশনকে টার্গেট করে, যেমন API লেভেল, তাহলে আপনাকে প্রতিটি বিল্ড ভেরিয়েন্টের জন্য একই অ্যাপ্লিকেশন আইডি ব্যবহার করতে হবে কিন্তু প্রতিটি APK-কে আলাদা versionCode দিতে হবে। আরও তথ্যের জন্য, একাধিক APK সাপোর্ট সম্পর্কে পড়ুন। AAB ব্যবহার করে প্রকাশ করার ক্ষেত্রে কোনও প্রভাব পড়ে না, কারণ এটি একটি আর্টিফ্যাক্ট ব্যবহার করে যা ডিফল্ট হিসেবে একটি ভার্সন কোড ও অ্যাপ্লিকেশন আইডি ব্যবহার করে।

পরামর্শ: আপনার ম্যানিফেস্ট ফাইলে অ্যাপ্লিকেশন আইডি রেফারেন্স হিসেবে ব্যবহার করতে হলে, আপনি যেকোনও ম্যানিফেস্ট অ্যাট্রিবিউটে ${applicationId} প্লেসহোল্ডার ব্যবহার করতে পারেন। বিল্ড করার সময়, Gradle এই ট্যাগটি আসল অ্যাপ্লিকেশন আইডি দিয়ে প্রতিস্থাপন করে। আরও তথ্যের জন্য, ম্যানিফেস্টে বিল্ড ভেরিয়েবল ইনজেক্ট করা দেখুন।

ফ্লেভার ডাইমেনসনের সাথে একাধিক প্রোডাক্ট ফ্লেভার একত্রিত করুন

কিছু ক্ষেত্রে, আপনি একাধিক প্রোডাক্ট ফ্লেভার থেকে কনফিগারেশন একত্রিত করতে চাইতে পারেন। যেমন, আপনি API লেভেলের উপর ভিত্তি করে "সম্পূর্ণ" এবং "ডেমো" প্রোডাক্ট ফ্লেভারের জন্য আলাদা কনফিগারেশন তৈরি করতে চাইতে পারেন। এটি করার জন্য, Android Gradle প্লাগ-ইন আপনাকে ফ্লেভার ডাইমেনশন হিসেবে প্রোডাক্ট ফ্লেভারের একাধিক গ্রুপ তৈরি করতে দেয়।

আপনার অ্যাপ তৈরি করার সময়, Gradle আপনার সংজ্ঞায়িত প্রতিটি ফ্লেভার ডাইমেনশন থেকে প্রোডাক্ট ফ্লেভার কনফিগারেশনকে বিল্ড টাইপ কনফিগারেশনের সাথে একত্রিত করে চূড়ান্ত বিল্ড ভ্যারিয়েন্ট তৈরি করে। Gradle একই ফ্লেভার ডাইমেনসনের প্রোডাক্ট ফ্লেভার একত্রিত করে না।

নিম্নলিখিত কোড স্যাম্পেল flavorDimensions প্রপার্টি ব্যবহার করে "full" ও "demo" প্রোডাক্ট ফ্লেভার গ্রুপ করার জন্য "mode" ফ্লেভার ডাইমেনশন এবং 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"
      ...
    }
  }
}
...

গ্ৰুভি

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

প্রতিটি প্রোডাক্ট ফ্লেভার ও বিল্ড ভেরিয়েন্টের জন্য আপনি যে সোর্স সেট ডিরেক্টরি তৈরি করতে পারেন, তার পাশাপাশি প্রোডাক্ট ফ্লেভারের প্রতিটি কম্বিনেশন-এর জন্যও সোর্স সেট ডিরেক্টরি তৈরি করতে পারবেন। যেমন, আপনি src/demoMinApi24/java/ ডিরেক্টরিতে Java সোর্স তৈরি করে যোগ করতে পারেন এবং Gradle শুধুমাত্র সেইসব সোর্স ব্যবহার করে যেগুলি দুটি প্রোডাক্ট ফ্লেভারকে একত্রিত করে ভেরিয়েন্ট তৈরি করে।

প্রোডাক্ট ফ্লেভারের কম্বিনেশনের জন্য আপনার তৈরি করা সোর্স সেটের অগ্রাধিকার, প্রতিটি আলাদা প্রোডাক্ট ফ্লেভারের সোর্স সেটের চেয়ে বেশি। সোর্স সেট এবং Gradle কীভাবে রিসোর্স মার্জ করে সেই সম্পর্কে আরও জানতে, সোর্স সেট তৈরি করা সংক্রান্ত বিভাগটি পড়ুন।

ভেরিয়েন্ট ফিল্টার করুন

আপনার কনফিগার করা প্রোডাক্ট ফ্লেভার ও বিল্ড টাইপের প্রতিটি সম্ভাব্য কম্বিনেশনের জন্য Gradle একটি বিল্ড ভেরিয়েন্ট তৈরি করে। তবে, এমন কিছু বিল্ড ভেরিয়েন্ট থাকতে পারে যেগুলি আপনার প্রয়োজন নেই বা আপনার প্রোজেক্টের প্রসঙ্গে সেগুলি প্রাসঙ্গিক নয়। নির্দিষ্ট কিছু বিল্ড ভেরিয়েন্ট কনফিগারেশন সরাতে, আপনার মডিউল-লেভেল build.gradle.kts ফাইলে একটি ভেরিয়েন্ট ফিল্টার তৈরি করুন।

উদাহরণ হিসেবে আগের বিভাগের বিল্ড কনফিগারেশন ব্যবহার করে, ধরে নিন যে আপনি অ্যাপের ডেমো ভার্সনের জন্য শুধুমাত্র API লেভেল ২৩ এবং তার থেকে বেশি লেভেল সাপোর্ট করার পরিকল্পনা করছেন। আপনি 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
        }
    }
}
...

গ্ৰুভি

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 টাস্ক প্রদান করে যা আপনাকে দেখায় যে কীভাবে আপনার প্রতিটি বিল্ড টাইপ, প্রোডাক্ট ফ্লেভার এবং বিল্ড ভ্যারিয়েন্টের জন্য ফাইল সাজাতে হয়। যেমন, টাস্ক আউটপুট থেকে নেওয়া নিম্নলিখিত স্যাম্পেল "debug" বিল্ড টাইপের জন্য 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-এ ডবল-ক্লিক করুন।

    টাস্ক ফোল্ডার দেখতে, সিঙ্ক করার সময় আপনাকে অবশ্যই Gradle-কে টাস্ক লিস্ট তৈরি করতে দিতে হবে। এটি করতে, নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করুন:

    1. File > Settings > Experimental (macOS-এ Android Studio > Settings > Experimental) বিকল্পে ক্লিক করুন।
    2. 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 > Values XML File বিকল্প বেছে নিন।
  2. XML ফাইলের নাম লিখুন অথবা ডিফল্ট নাম রেখে দিন।
  3. টার্গেট সোর্স সেট-এর পাশে থাকা মেনু থেকে, ডিবাগ বিকল্প বেছে নিন।
  4. সম্পূর্ণ করুন বিকল্পে ক্লিক করুন।

কারণ "ডিবাগ" বিল্ড টাইপ টার্গেট সোর্স সেট হিসেবে নির্দিষ্ট করা হয়েছে, Android Studio অটোমেটিক প্রয়োজনীয় ডিরেক্টরি তৈরি করে যখন এটি XML ফাইল তৈরি করে। ফলাফল হিসেবে পাওয়া ডিরেক্টরি স্ট্রাকচারটি ছবি ১-এর মতো দেখতে হয়।

ছবি ১. "ডিবাগ" বিল্ড টাইপের জন্য নতুন সোর্স সেট ডিরেক্টরি।

অ্যাক্টিভ সোর্স সেটের আইকনে একটি সবুজ ইন্ডিকেটর থাকে যা দেখায় যে সেগুলি অ্যাক্টিভ আছে। debug সোর্স সেটটি [main]-এর সাথে যুক্ত করা হয়েছে যাতে দেখানো যায় যে এটি main সোর্স সেটে মার্জ করা হবে।

একই পদ্ধতি ব্যবহার করে, আপনি প্রোডাক্ট ফ্লেভারের জন্য সোর্স সেট ডিরেক্টরিও তৈরি করতে পারেন, যেমন src/demo/ এবং বিল্ড ভেরিয়েন্ট, যেমন src/demoDebug/। এছাড়াও, আপনি টেস্টিং সোর্স সেট তৈরি করতে পারেন যা নির্দিষ্ট বিল্ড ভেরিয়েন্টকে টার্গেট করে, যেমন src/androidTestDemoDebug/। আরও জানতে, সোর্স সেট পরীক্ষা করা সম্পর্কে পড়ুন।

ডিফল্ট সোর্স সেট কনফিগারেশন পরিবর্তন করুন

আপনার কাছে যদি এমন সোর্স থাকে যা Gradle-এর প্রত্যাশিত ডিফল্ট সোর্স সেট ফাইল স্ট্রাকচারে সাজানো নেই, যেমনটি সোর্স সেট তৈরি করা সম্পর্কে আগের বিভাগে বর্ণনা করা হয়েছে, তাহলে আপনি sourceSets ব্লক ব্যবহার করে সোর্স সেটের প্রতিটি কম্পোনেন্টের জন্য Gradle কোথায় ফাইল সংগ্রহ করবে তা পরিবর্তন করতে পারেন।

sourceSets ব্লকটি অবশ্যই android ব্লকে থাকতে হবে। আপনাকে সোর্স ফাইলগুলি স্থানান্তর করতে হবে না; আপনাকে শুধু Gradle-কে পাথ(গুলি) প্রদান করতে হবে, যা মডিউল-লেভেল build.gradle.kts ফাইলের সাথে সম্পর্কিত, যেখানে Gradle প্রতিটি সোর্স সেট কম্পোনেন্টের জন্য ফাইলগুলি খুঁজে পেতে পারে। আপনি কোন কোন কম্পোনেন্ট কনফিগার করতে পারবেন এবং সেগুলি একাধিক ফাইল বা ডিরেক্টরিতে ম্যাপ করতে পারবেন কিনা তা জানতে, Android Gradle প্লাগ-ইন API রেফারেন্স দেখুন।

নিম্নলিখিত কোড স্যাম্পেল 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")
      ...
  }
}
...

গ্ৰুভি

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 কীওয়ার্ডের আগে বিল্ড ভেরিয়েন্ট বা টেস্টিং সোর্স সেটের নাম প্রিফিক্স হিসেবে যোগ করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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 এবং তার পরবর্তী ভার্সনে একটি নতুন ডিপেন্ডেন্সি মেকানিজম অন্তর্ভুক্ত আছে যা লাইব্রেরি ব্যবহার করার সময় অটোমেটিক ভেরিয়েন্ট ম্যাচ করে। যেমন, কোনও অ্যাপের debug ভেরিয়েন্ট অটোমেটিক কোনও লাইব্রেরির debug ভেরিয়েন্ট ব্যবহার করে। এটি ফ্লেভার ব্যবহার করার সময়ও কাজ করে: কোনও অ্যাপের freeDebug ভেরিয়েন্ট কোনও লাইব্রেরির freeDebug ভেরিয়েন্ট ব্যবহার করবে।

প্লাগ-ইন যাতে সঠিকভাবে ভেরিয়েন্ট ম্যাচ করতে পারে, তার জন্য আপনাকে ম্যাচিং ফলব্যাক প্রদান করতে হবে, যেমনটি নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে, যেখানে সরাসরি ম্যাচ করা সম্ভব নয়।

যেমন, ধরুন আপনার অ্যাপ "স্টেজিং" নামে একটি বিল্ড টাইপ কনফিগার করে, কিন্তু এর একটি লাইব্রেরি ডিপেন্ডেন্সি তা করে না। প্লাগ-ইন আপনার অ্যাপের "স্টেজিং" ভার্সন তৈরি করার চেষ্টা করলে, এটি লাইব্রেরির কোন ভার্সন ব্যবহার করতে হবে তা জানতে পারবে না এবং আপনি নিচে উল্লেখ করা মেসেজের মতো একটি সমস্যার মেসেজ দেখতে পাবেন:

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

ভ্যারিয়েন্ট ম্যাচিং সম্পর্কিত বিল্ড সংক্রান্ত সমস্যার সমাধান করা

প্লাগ-ইনে DSL এলিমেন্ট অন্তর্ভুক্ত থাকে যা আপনাকে Gradle-এর পরিস্থিতি সমাধান করার পদ্ধতি নিয়ন্ত্রণ করতে সাহায্য করে যেখানে একটি অ্যাপ এবং ডিপেন্ডেন্সির মধ্যে সরাসরি ভেরিয়েন্ট ম্যাচ করা সম্ভব নয়।

ভেরিয়েন্ট-অ্যাওয়ার ডিপেন্ডেন্সি ম্যাচিং সংক্রান্ত সমস্যার তালিকা এবং DSL প্রপার্টি ব্যবহার করে কীভাবে সেগুলি সমাধান করবেন তা নিচে দেওয়া হল:

  • আপনার অ্যাপে এমন একটি বিল্ড টাইপ অন্তর্ভুক্ত রয়েছে যা লাইব্রেরি ডিপেন্ডেন্সিতে নেই।

    যেমন, আপনার অ্যাপে "স্টেজিং" বিল্ড টাইপ অন্তর্ভুক্ত আছে, কিন্তু ডিপেন্ডেন্সিতে শুধু "ডিবাগ" এবং "রিলিজ" বিল্ড টাইপ অন্তর্ভুক্ত আছে।

    মনে রাখবেন, লাইব্রেরি ডিপেন্ডেন্সিতে এমন কোনও বিল্ড টাইপ থাকলে কোনও সমস্যা হয় না যা আপনার অ্যাপে নেই। কারণ প্লাগ-ইন কখনও ডিপেন্ডেন্সি থেকে সেই বিল্ড টাইপের জন্য অনুরোধ করে না।

    প্রদত্ত বিল্ড টাইপের জন্য বিকল্প ম্যাচ নির্দিষ্ট করতে 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']
            }
        }
    }
  • অ্যাপ এবং লাইব্রেরি ডিপেন্ডেন্সি, দুটিতেই আছে এমন কোনও ফ্লেভার ডাইমেনসনের ক্ষেত্রে, আপনার অ্যাপে এমন ফ্লেভার আছে যা লাইব্রেরিতে নেই।

    যেমন, আপনার অ্যাপ এবং এর লাইব্রেরি ডিপেন্ডেন্সি, দুটিতেই "tier" ফ্লেভার ডাইমেনসন অন্তর্ভুক্ত থাকে। তবে, অ্যাপে "টিয়ার" ডাইমেনশনে "ফ্রি" ও "পেড" ফ্লেভার অন্তর্ভুক্ত থাকে, কিন্তু একই ডাইমেনশনের জন্য ডিপেন্ডেন্সিতে শুধু "ডেমো" ও "পেড" ফ্লেভার অন্তর্ভুক্ত থাকে।

    মনে রাখবেন, কোনও নির্দিষ্ট ফ্লেভার ডাইমেনশন যা অ্যাপ এবং তার লাইব্রেরি ডিপেন্ডেন্সি, উভয় ক্ষেত্রেই আছে, সেক্ষেত্রে লাইব্রেরিতে এমন কোনও প্রোডাক্ট ফ্লেভার থাকলে কোনও সমস্যা হয় না যা আপনার অ্যাপে নেই। কারণ প্লাগ-ইন কখনই ডিপেন্ডেন্সি থেকে সেই ফ্লেভারের জন্য অনুরোধ করে না।

    অ্যাপের "ফ্রি" প্রোডাক্ট ফ্লেভারের জন্য বিকল্প মিল নির্দিষ্ট করতে 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")
            }
        }
    }

    গ্ৰুভি

    // 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" ভার্সন ব্যবহার করবে।

    defaultConfig ব্লকে missingDimensionStrategy ব্যবহার করে প্লাগ-ইনের জন্য ডিফল্ট ফ্লেভার নির্দিষ্ট করুন যাতে প্রতিটি অনুপস্থিত ডাইমেনশন থেকে বেছে নেওয়া যায়, যেমনটি নিম্নলিখিত স্যাম্পেলে দেখানো হয়েছে। এছাড়াও, আপনি 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 {}
        }
    }

আরও তথ্যের জন্য, Android Gradle প্লাগ-ইন DSL রেফারেন্সে matchingFallbacks এবং missingDimensionStrategy দেখুন।

স্বাক্ষর সংক্রান্ত সেটিংস কনফিগার করুন

আপনি এই বিল্ডের জন্য সাইনিং কনফিগারেশন স্পষ্টভাবে উল্লেখ না করলে, Gradle আপনার রিলিজ বিল্ডের APK বা AAB সাইন করে না। আপনার কাছে এখনও কোনও সাইনিং কী না থাকলে, Android Studio ব্যবহার করে একটি আপলোড কী ও কীস্টোর তৈরি করুন।

Gradle বিল্ড কনফিগারেশন ব্যবহার করে আপনার রিলিজ বিল্ড টাইপের জন্য সাইনিং কনফিগারেশন ম্যানুয়ালি কনফিগার করতে:

  1. একটি keystore তৈরি করুন। কীস্টোর হল একটি বাইনারি ফাইল যার মধ্যে ব্যক্তিগত কী-এর সেট থাকে। আপনাকে অবশ্যই নিজের কীস্টোর নিরাপদ ও সুরক্ষিত জায়গায় রাখতে হবে।
  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")
            }
        }
    }

    গ্ৰুভি

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

মনে রাখবেন: বিল্ড ফাইলের মধ্যে আপনার রিলিজ কী এবং কীস্টোরের পাসওয়ার্ড অন্তর্ভুক্ত করা নিরাপত্তার দিক থেকে ভাল অভ্যাস নয়। পরিবর্তে, এনভায়রনমেন্ট ভেরিয়েবেল থেকে এইসব পাসওয়ার্ড পেতে বিল্ড ফাইল কনফিগার করুন অথবা বিল্ড প্রসেস যাতে এইসব পাসওয়ার্ডের জন্য আপনাকে প্রম্পট করে তার ব্যবস্থা করুন।

এনভায়রনমেন্ট ভেরিয়েবল থেকে এইসব পাসওয়ার্ড পেতে:

Kotlin

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

গ্ৰুভি

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

অন্যথায়, আপনি স্থানীয় প্রপার্টি ফাইল থেকে keystore লোড করতে পারবেন। নিরাপত্তার কারণে, সোর্স কন্ট্রোলে এই ফাইল যোগ করবেন না। পরিবর্তে, প্রতিটি ডেভেলপারের জন্য এটি লোকালভাবে সেট-আপ করুন। আরও জানতে, আপনার বিল্ড ফাইল থেকে সাইন-ইন সংক্রান্ত তথ্য সরিয়ে দিন নিবন্ধটি পড়ুন।

এই প্রসেস সম্পূর্ণ করার পরে, আপনি নিজের অ্যাপ ডিস্ট্রিবিউট করতে এবং Google Play-তে প্রকাশ করতে পারবেন।

সতর্কতা: আপনার কীস্টোর ও ব্যক্তিগত কী নিরাপদ ও সুরক্ষিত জায়গায় রাখুন এবং নিশ্চিত করুন যে আপনার কাছে সেগুলির সুরক্ষিত ব্যাক-আপ আছে। আপনি Play অ্যাপ সাইনিং ব্যবহার করলে এবং আপলোড কী হারিয়ে ফেললে, Play Console ব্যবহার করে রিসেট করার অনুরোধ করতে পারবেন। আপনি যদি Play অ্যাপ সাইনিং (আগস্ট ২০২১-এর আগে তৈরি করা অ্যাপের জন্য) ছাড়া কোনও অ্যাপ প্রকাশ করেন এবং আপনার অ্যাপ সাইনিং কী হারিয়ে ফেলেন, তাহলে আপনার অ্যাপের কোনও আপডেট প্রকাশ করতে পারবেন না, কারণ আপনাকে সবসময় একই কী দিয়ে আপনার অ্যাপের সব ভার্সন সাইন করতে হবে।

Wear OS অ্যাপে সাইন-ইন করা

Wear OS অ্যাপ প্রকাশ করার সময়, ওয়াচ APK এবং ঐচ্ছিক ফোন APK, দুটিই একই কী দিয়ে সাইন করা থাকতে হবে। Wear OS অ্যাপ প্যাকেজ ও সাইন করা সম্পর্কে আরও জানতে, Wear অ্যাপ প্যাকেজ ও ডিস্ট্রিবিউট করুন দেখুন।