Android ডেভেলপমেন্টে Product Flavor হল একটি Gradle মেকানিজম যা একটি শেয়ার্ড কোড বেস থেকে একই অ্যাপ্লিকেশনের একাধিক ভ্যারিয়েন্ট তৈরি করার অনুমতি দেয়। প্রতিটি flavor-এর নিজস্ব applicationId, রিসোর্স, নির্ভরতা এবং কার্যকারিতা থাকতে পারে — যেমন, বিনামূল্যে এবং অর্থপ্রদানের সংস্করণ। Google Android Developers, 2025 অনুযায়ী, Product Flavors Build Variants সিস্টেমের অংশ এবং flavorDimensions-এর মাধ্যমে Build Types-এর সাথে মিলিত হয়। Google Play-তে একাধিক অ্যাপ সংস্করণ প্রকাশ করার এটি মানক পদ্ধতি।
মূল বিষয়
Product Flavor android.productFlavors ব্লকের মধ্যে একটি Gradle কনফিগারেশন যা পণ্যের ভ্যারিয়েন্ট বর্ণনা করে। প্রতিটি flavor applicationId, versionName, versionCode, minSdkVersion, targetSdkVersion, signingConfig এবং defaultConfig-এর অন্যান্য প্যারামিটার ওভাররাইড করতে পারে। Product Flavors-এর পরিমাণের কোনো সীমা নেই: একটি প্রজেক্টে 2, 5 বা 10টি flavors থাকতে পারে — Gradle সব কম্বিনেশন হ্যান্ডেল করে।
Product Flavor codebase reuse সমস্যার সমাধান করে — যখন একটি রিপোজিটরি থেকে একাধিক ভিন্ন অ্যাপ্লিকেশন তৈরি করতে হয়। সাধারণ পরিস্থিতি: বিজ্ঞাপন সহ বিনামূল্যের সংস্করণ এবং ছাড়া অর্থপ্রদানের সংস্করণ; সীমিত কার্যকারিতা সহ ডেমো সংস্করণ; কর্পোরেট এবং ভোক্তা সংস্করণ; বিভিন্ন ক্লায়েন্টের জন্য white-label অ্যাপ। Product Flavors ছাড়া, প্রতিটি সংস্করণকে আলাদা প্রজেক্টে রক্ষণাবেক্ষণ করতে হবে, যা 60-70% কোড ডুপ্লিকেশনের দিকে নিয়ে যায়।
ঐতিহাসিকভাবে, Product Flavors Android Gradle Plugin 0.9 (2013)-এ ant কনফিগারেশনের প্রতিস্থাপন হিসেবে আবির্ভূত হয়েছিল। তার আগে, ডেভেলপাররা বিভিন্ন সংস্করণের জন্য আলাদা প্রজেক্ট বা বিল্ডের আগে ম্যানুয়াল রিসোর্স প্রতিস্থাপন ব্যবহার করতেন। AGP-তে flavors-এর অন্তর্ভুক্তি পদ্ধতিটিকে একীভূত করেছে এবং এটিকে মানক করে তুলেছে। JetBrains, 2024-এর একটি জরিপ অনুসারে, একাধিক সংস্করণের 78% Android প্রজেক্ট Product Flavors ব্যবহার করে, বাকিরা BuildConfig বা reflection-এর মাধ্যমে ম্যানুয়াল সুইচিং ব্যবহার করে।
Build Type বিল্ড প্রক্রিয়া পরিচালনা করে (ডিবাগিং সহ debug, অপ্টিমাইজেশন সহ release)। Product Flavor বিল্ড বিষয়বস্তু পরিচালনা করে (অর্থপ্রদানের বৈশিষ্ট্য ছাড়া free, সেগুলি সহ paid)। Build Type হল একটি পরিকাঠামো সেটিং, Product Flavor হল একটি পণ্য সেটিং। উভয় ধারণা অর্থোগোনাল: free flavor-এর debug বিল্ড free flavor-এর release বিল্ড থেকে শুধুমাত্র কম্পাইলেশন প্যারামিটারে আলাদা, কার্যকারিতায় নয়। Product Flavor ডিবাগার নিষ্ক্রিয় করতে ব্যবহার করা যায় না — এটি Build Type-এর কাজ।
Flavor Dimensions Product Flavors-কে স্বাধীন বিভাগে গ্রুপ করার একটি প্রক্রিয়া। যদি কোনো অ্যাপের বিনামূল্যে/অর্থপ্রদানের সংস্করণ এবং আলাদাভাবে আমেরিকান/ইউরোপীয় অঞ্চল থাকে, তাহলে flavors দুটি মাত্রায় গ্রুপ করা হয়: "tier" (free, paid) এবং "region" (us, eu)। Gradle মাত্রাগুলির কার্টেসিয়ান গুণফল তৈরি করে: freeUs, freeEu, paidUs, paidEu — 4টি ভ্যারিয়েন্ট। মাত্রা ছাড়া, Gradle চারটি flavors-কে একটি একক সমতল হিসেবে বিবেচনা করবে এবং শুধুমাত্র একটি নির্বাচন করা যাবে।
মাত্রাগুলি flavorDimensions ব্লকে একটি স্ট্রিং বা স্ট্রিং-এর তালিকা হিসেবে ঘোষণা করা হয়। মাত্রাগুলির ক্রম source sets-এর অগ্রাধিকারকে প্রভাবিত করে: প্রথম মাত্রার সর্বোচ্চ অগ্রাধিকার থাকে। যদি মাত্রা A (tier) প্রথমে নির্দিষ্ট করা হয়, তাহলে রিসোর্স বিরোধের ক্ষেত্রে src/free/, src/us/-কে ওভাররাইড করবে। ক্রম Variant-এর নাম কীভাবে গঠিত হয় তাও প্রভাবিত করে: প্রথমে প্রথম মাত্রার flavors আসে, তারপর দ্বিতীয়টির, তারপর Build Type: freeUsDebug।
মাত্রার সংখ্যা সীমিত নয়, তবে প্রতিটি নতুন মাত্রা Build Variants-এর সংখ্যা গুণিত করে। 4টি মাত্রা (প্রতিটিতে 2টি flavors) এবং 2টি build types সহ একটি প্রজেক্টের জন্য, আপনি 2 × 2 × 2 × 2 × 2 = 32টি ভ্যারিয়েন্ট পান। ব্যবহারিক সীমা হল 3টি মাত্রা (সর্বোচ্চ 8-12টি ভ্যারিয়েন্ট)। এর চেয়ে বেশি হলে, Gradle কনফিগারেশন ধীর হয়ে যায় এবং Android Studio-তে Build Variants প্যানেল অপাঠ্য হয়ে যায়।
android {
flavorDimensions "tier", "api"
productFlavors {
free {
dimension "tier"
applicationId "com.example.app.free"
versionNameSuffix "-free"
}
paid {
dimension "tier"
applicationId "com.example.app.paid"
}
minApi21 {
dimension "api"
minSdk 21
}
minApi26 {
dimension "api"
minSdk 26
}
}
}
// ফলাফল: freeMinApi21, freeMinApi26, paidMinApi21, paidMinApi26
// প্রত্যেক × debug/release = 8টি Build Variants
Product Flavor তৈরি করতে, android-এর ভিতরে একটি productFlavors ব্লক যোগ করতে হবে, flavor-এর নাম এবং এর প্যারামিটার নির্দিষ্ট করতে হবে। সর্বনিম্ন flavor ঘোষণা হল নাম এবং মাত্রা। অন্যান্য সমস্ত প্যারামিটার defaultConfig থেকে উত্তরাধিকারসূত্রে পাওয়া যায় এবং ওভাররাইড করা যেতে পারে। Flavor সম্পূর্ণরূপে defaultConfig উত্তরাধিকার সূত্রে পায়, যার মধ্যে applicationId, versionCode, testInstrumentationRunner অন্তর্ভুক্ত।
প্রতিটি flavor applicationId ওভাররাইড করতে পারে — এটি একই ডিভাইসে একসাথে একাধিক অ্যাপ সংস্করণ ইনস্টল করার অনুমতি দেয়। উদাহরণস্বরূপ, বিনামূল্যের সংস্করণ হবে com.example.app.free, অর্থপ্রদানের — com.example.app.paid। যদি applicationId ওভাররাইড না করা হয়, তবে সব flavors-এর একই আইডেন্টিফায়ার থাকবে এবং সেগুলি পাশাপাশি ইনস্টল করা যাবে না। applicationId অবশ্যই ম্যানিফেস্টের প্যাকেজের সাথে মিলতে হবে (যদি না applicationIdSuffix ব্যবহার করা হয়)।
AGP 8+ build.gradle-এর জন্য Groovy-এর পরিবর্তে Kotlin DSL ব্যবহার করার পরামর্শ দেয়। Kotlin DSL কনফিগারেশনে type-safe অ্যাক্সেস প্রদান করে: IDE প্যারামিটারের নাম সুপারিশ করে, কম্পাইল টাইমে টাইপ চেক করে এবং ত্রুটিগুলি হাইলাইট করে। Product Flavors-এর জন্য Groovy থেকে Kotlin DSL-এ মাইগ্রেশনে সাধারণত উদ্ধৃতিগুলিকে বন্ধনী দিয়ে প্রতিস্থাপন এবং টাইপ যোগ করা অন্তর্ভুক্ত। AGP পশ্চাদমুখী-সামঞ্জস্যপূর্ণ — উভয় সিনট্যাক্স একই প্রজেক্টের মধ্যে সমান্তরালভাবে কাজ করে।
// build.gradle.kts — Kotlin DSL
android {
flavorDimensions += "tier"
productFlavors {
register("free") {
dimension = "tier"
applicationId = "com.example.app.free"
versionNameSuffix = "-free"
buildConfigField("boolean", "IS_PREMIUM", "false")
}
register("paid") {
dimension = "tier"
applicationId = "com.example.app.paid"
versionNameSuffix = "-paid"
buildConfigField("boolean", "IS_PREMIUM", "true")
}
}
}
প্রতিটি Product Flavor তার নিজস্ব source set তৈরি করে — একটি src/<flavorName>/ ডিরেক্টরি। এই ডিরেক্টরিতে ওভাররাইড করা রিসোর্স, সোর্স ফাইল এবং ম্যানিফেস্ট থাকতে পারে। Flavor source set main-এর উপরে একটি ওভারলে হিসাবে কাজ করে: src/free/res/-এর ফাইলগুলি একই নামের src/main/res/-এর ফাইলগুলিকে ওভাররাইড করে। এটি মূল কোড পরিবর্তন না করেই প্রতিটি flavor-এর জন্য আলাদা স্ট্রিং, আইকন, রঙ এবং লেআউট রাখার অনুমতি দেয়।
Java/Kotlin ক্লাস ওভাররাইড করার জন্য দুটি পদ্ধতি রয়েছে: flavor-নির্দিষ্ট বাস্তবায়ন (প্রতিটি flavor-এ একটি অ্যাবস্ট্রাক্ট ক্লাস বাস্তবায়ন) এবং BuildConfig ফিল্ড (কোডে শাখাকরণ)। প্রথম পদ্ধতিটি বেশি পরিষ্কার: আপনি main-এ একটি ইন্টারফেস বা অ্যাবস্ট্রাক্ট ক্লাস সংজ্ঞায়িত করেন এবং src/free/ এবং src/paid/-এ কংক্রিট বাস্তবায়ন। বিল্ডের সময়, শুধুমাত্র বর্তমান flavor-এর বাস্তবায়ন কম্পাইল হয়। এটি একসাথে সুবিধা প্রদান করে: ছোট APK আকার (অর্থপ্রদানের কোড বিনামূল্যের সংস্করণে যায় না) এবং নিরাপত্তা (ভুলবশত অর্থপ্রদানের ফাংশন কল করা অসম্ভব)।
Flavor source set-এ AndroidManifest.xml প্রতিস্থাপন করে না বরং মূল ম্যানিফেস্টের সাথে মার্জ হয়। মার্জিং Android নিয়ম অনুসরণ করে: একই উপাদানে ডুপ্লিকেট অ্যাট্রিবিউট ওভাররাইড করা হয়, অনন্য যোগ করা হয়। উদাহরণস্বরূপ, যদি মূল ম্যানিফেস্ট INTERNET অনুমতি ঘোষণা করে এবং free না করে, ইন্টারনেট অনুমতি থাকে। তবে, tools:node="replace" একটি নির্দিষ্ট flavor-এর জন্য সম্পূর্ণ ম্যানিফেস্ট ব্লক প্রতিস্থাপনের অনুমতি দেয়। এটি উপযোগী যখন বিভিন্ন flavors-এর বিভিন্ন অনুমতির প্রয়োজন হয় (অর্থপ্রদানের সংস্করণের জন্য SD কার্ড লেখা, বিনামূল্যের জন্য ক্যামেরা)।
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:label="Free App"
tools:replace="android:label">
</application>
</manifest>
একটি সাধারণ পরিস্থিতি বিবেচনা করুন: free — বিজ্ঞাপন এবং মৌলিক বৈশিষ্ট্য সহ একটি সংস্করণ, paid — বিজ্ঞাপন ছাড়া, বর্ধিত কার্যকারিতা সহ। বিনামূল্যের সংস্করণের জন্য, applicationId "com.example.app.free"-এ সেট করা হয়েছে, অর্থপ্রদানের জন্য — "com.example.app.paid"। উভয় সংস্করণ একই ডিভাইসে একসাথে ইনস্টল করা যেতে পারে, কারণ applicationId Android সিস্টেমে অ্যাপ্লিকেশনের অনন্য শনাক্তকারী।
স্থাপত্যগতভাবে, পৃথকীকরণ ইন্টারফেস + flavor বাস্তবায়ন-এর মাধ্যমে নির্মিত। মূল source set-এ, PaymentService ইন্টারফেস ঘোষণা করা হয়েছে। src/free/-এ, একটি বাস্তবায়ন রয়েছে যা AdMob-এর মাধ্যমে অর্থপ্রদানের আগে একটি বিজ্ঞাপন দেখায়। src/paid/-এ — একটি বাস্তবায়ন যা সরাসরি পেমেন্ট গেটওয়েতে যায়। PaymentService ব্যবহার করা কোড জানে না কোন বাস্তবায়ন লোড করা হয়েছে — এটি কম্পাইল টাইমে সমাধান করা হয়। এই পদ্ধতি গ্যারান্টি দেয় যে সাবস্ক্রিপশন ম্যানেজমেন্ট কোড বিনামূল্যের সংস্করণে শেষ হবে না, এমনকি ডেভেলপার ভুলবশত এটি কল করলেও।
নির্ভরতা অন্তর্ভুক্ত/বাদ দেওয়ার কারণে বিভিন্ন flavors-এর জন্য APK আকার 5-15 MB পর্যন্ত ভিন্ন হতে পারে। একটি নির্দিষ্ট flavor থেকে লাইব্রেরি বাদ দিতে, build.gradle-এ flavor-নির্দিষ্ট নির্ভরতা ব্যবহার করুন: freeImplementation 'com.google.android.gms:play-services-ads:23.0.0'। এই নির্ভরতা শুধুমাত্র বিনামূল্যের ভ্যারিয়েন্টের জন্য যোগ করা হবে এবং অর্থপ্রদানের সংস্করণের আকার বাড়াবে না। ভাগ করা নির্ভরতার জন্য, implementation ব্যবহার করুন — সব flavors সেগুলি অন্তর্ভুক্ত করে।
// src/main/kotlin/com/example/payment/PaymentService.kt
interface PaymentService {
fun processOrder(amount: Double, callback: (PaymentResult) -> Unit)
}
// src/free/kotlin/.../FreePaymentService.kt
class FreePaymentService : PaymentService {
override fun processOrder(amount: Double, callback: (PaymentResult) -> Unit) {
AdManager.showInterstitial {
PaymentGateway.charge(amount, callback)
}
}
}
// src/paid/kotlin/.../PaidPaymentService.kt
class PaidPaymentService : PaymentService {
override fun processOrder(amount: Double, callback: (PaymentResult) -> Unit) {
PaymentGateway.charge(amount, callback)
}
}
মাল্টি-মডিউল প্রজেক্টে, লাইব্রেরি মডিউলগুলির নিজস্ব Product Flavors নাও থাকতে পারে, যা একটি সমস্যা তৈরি করে: লাইব্রেরি একবার (release হিসেবে) তৈরি হয়, অন্যদিকে flavor সহ অ্যাপ মডিউল সংশ্লিষ্ট ভ্যারিয়েন্টের সাথে লাইব্রেরি আশা করে। AGP 8.1 থেকে শুরু করে, লাইব্রেরিগুলি publishing.multipleVariants ব্লকের মাধ্যমে একাধিক ভ্যারিয়েন্ট প্রকাশ করতে পারে — এটি লাইব্রেরির সমস্ত flavor ভ্যারিয়েন্ট একটি maven রিপোজিটরিতে প্রকাশ করার অনুমতি দেয়, এবং অ্যাপ মডিউল স্বয়ংক্রিয়ভাবে সঠিক ভ্যারিয়েন্ট নির্বাচন করবে।
একটি বিকল্প পদ্ধতি হল লাইব্রেরিতে একই flavorDimensions এবং productFlavors ঘোষণা করা যা অ্যাপ মডিউলে রয়েছে। AGP স্বয়ংক্রিয়ভাবে একটি মাত্রার মধ্যে সঠিক নাম মিলানোর মাধ্যমে flavors মিলিয়ে নেয়। যদি লাইব্রেরিতে flavor-এর নাম অ্যাপের নামের সাথে মেলে, AGP সামঞ্জস্যপূর্ণ ভ্যারিয়েন্ট তৈরি করবে। রক্ষণাবেক্ষণের সহজতার জন্য, সাধারণ flavor সংজ্ঞাগুলি একটি Convention Plugin-এ বের করার পরামর্শ দেওয়া হয় — একটি Gradle প্লাগইন যা প্রজেক্টের সমস্ত মডিউলে প্রয়োগ করা হয়।
প্রকাশনার উদ্দেশ্যে নয় এমন লাইব্রেরির (অভ্যন্তরীণ মডিউল) জন্য, রুট প্রজেক্টের build.gradle-এর মাধ্যমে flavors সিঙ্ক্রোনাইজ করা যথেষ্ট। Gradle subprojects পদ্ধতি প্রদান করে, যা সমস্ত সাব-প্রজেক্টে কনফিগারেশন প্রয়োগ করার অনুমতি দেয়। তবে, মনে রাখবেন যে subprojects-এ অত্যধিক কনফিগারেশন কনফিগারেশন ফেজকে ধীর করে দেয়। Convention Plugins ব্যবহার করার পরামর্শ দেওয়া হয় — এগুলি একবার কম্পাইল হয় এবং পুনরায় ব্যবহার করা হয়, যা কনফিগারেশনের সময় 15-30% কমিয়ে দেয়।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
পরিমাণের কোনো সীমা নেই, তবে প্রতিটি মাত্রা Build Variants-এর সংখ্যা গুণিত করে। একটি মাত্রায় 4টি flavors + 2টি build types = 8টি ভ্যারিয়েন্ট। দুটি মাত্রায় 4 + 4 = 16টি ভ্যারিয়েন্ট। 3টির বেশি মাত্রা এবং মোট 10-12টির বেশি ভ্যারিয়েন্ট ব্যবহার না করার পরামর্শ দেওয়া হয়।
হ্যাঁ, source set src/<flavor>/AndroidManifest.xml-এর মাধ্যমে। ম্যানিফেস্ট মূলের সাথে মার্জ হয়। সম্পূর্ণ ব্লক প্রতিস্থাপন করতে, tools:node="replace" ব্যবহার করুন। উদাহরণস্বরূপ, একটি নির্দিষ্ট flavor-এর জন্য অ্যাপ লেবেল বা অনুমতি পরিবর্তন করুন।
<flavorName>Implementation কনফিগারেশন ব্যবহার করুন। উদাহরণ: freeImplementation 'com.google.android.gms:play-services-ads:23.0.0'। এই নির্ভরতা শুধুমাত্র বিনামূল্যের ভ্যারিয়েন্ট তৈরি করার সময় অন্তর্ভুক্ত হবে। অর্থপ্রদানের জন্য: paidImplementation। সাধারণ নির্ভরতা implementation-এর মাধ্যমে নির্দিষ্ট করা হয়।
Product Flavor পণ্য সংস্করণ (free, paid, demo) সংজ্ঞায়িত করে, Build Type বিল্ড পদ্ধতি (debug, release) সংজ্ঞায়িত করে। Flavors applicationId, versionName, রিসোর্স ওভাররাইড করতে পারে। Build Type debuggable, minification, signing নিয়ন্ত্রণ করে। উভয়ই অর্থোগোনাল এবং Build Variant-এ মিলিত হয়।
হ্যাঁ, Product Flavors কোনো বিধিনিষেধ ছাড়াই Compose-এর সাথে কাজ করে। বিভিন্ন flavors-এর source sets বা অ্যাবস্ট্রাক্ট ক্লাস বাস্তবায়নের মাধ্যমে আলাদা Compose স্ক্রিন থাকতে পারে। আপনি flavor-নির্দিষ্ট Compose নির্ভরতাও যোগ করতে পারেন: freeImplementation 'androidx.compose.ui:ui-tooling'।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন