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) کے مسئلے کو حل کرتا ہے — جب ایک ہی ریپوزٹری سے متعدد مختلف ایپلیکیشنز بنانے کی ضرورت ہوتی ہے۔ عام منظرنامے: اشتہارات کے ساتھ مفت ورژن اور ان کے بغیر ادائیگی والا ورژن؛ محدود فعالیت کے ساتھ ڈیمو ورژن؛ کارپوریٹ اور صارفین کے ورژن؛ مختلف کلائنٹس کے لیے وائٹ لیبل ایپس۔ 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 ترتیب تک ٹائپ سیف رسائی فراہم کرتا ہے: 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں