הגדרת Flavor/Scheme לגרסאות אפליקציית מובייל
תארו לעצמכם: הסטארטאפ הפינטק שלכם משחרר אפליקציית white-label לשלושה בנקים. לכל אחד יש עיצוב משלו, נקודת קצה API ו-bundle משלו. צוות ה-QA צריך לבדוק את סביבת ה-staging מבלי לסכן נתוני production. ללא הגדרת Flavor/Scheme נכונה, תיתקלו בבלבול בשמות חבילות ולא תוכלו להתקין שתי גרסאות זו לצד זו. אנו פותרים זאת תוך 2–5 ימים באמצעות Product Flavors (אנדרואיד), Schemes/Targets (iOS) ותצורות Flutter. ב-5 שנים השלמנו מעל 30 פרויקטים—מפינטק ועד white-label B2B. אנו מבטיחים שלאחר ההגדרה, תוכלו להתקין את כל הגרסאות על מכשיר אחד בו-זמנית ללא התנגשויות.
כיצד להגדיר Flavors בפלטפורמות שונות?
אנדרואיד: Product Flavors
Product Flavors באנדרואיד יוצרים גרסאות אפליקציה נפרדות עם applicationId שונים, משאבים, קוד ותלויות.
android {
flavorDimensions += listOf("environment", "tier")
productFlavors {
create("dev") {
dimension = "environment"
applicationIdSuffix = ".dev"
versionNameSuffix = "-dev"
resValue("string", "app_name", "MyApp Dev")
}
create("staging") {
dimension = "environment"
applicationIdSuffix = ".staging"
versionNameSuffix = "-staging"
resValue("string", "app_name", "MyApp Staging")
}
create("production") {
dimension = "environment"
}
create("free") {
dimension = "tier"
applicationIdSuffix = ".free"
}
create("paid") {
dimension = "tier"
}
}
}זה יוצר מטריצה: android { flavorDimensions += listOf("environment", "tier") productFlavors { create("dev") { dimension = "environment" applicationIdSuffix = ".dev" versionNameSuffix = "-dev" resValue("string", "app_name", "MyApp Dev") } create("staging") { dimension = "environment" applicationIdSuffix = ".staging" versionNameSuffix = "-staging" resValue("string", "app_name", "MyApp Staging") } create("production") { dimension = "environment" } create("free") { dimension = "tier" applicationIdSuffix = ".free" } create("paid") { dimension = "tier" } } } , devFreeDebug, devPaidRelease וכו'. בדרך כלל אנו משתמשים רק בשילובים הדרושים ומסננים במפורש את השאר באמצעות productionFreeRelease. משאבים ספציפיים ל-Flavor נכנסים אל variantFilter, src/dev/res/, src/staging/res/. קוד Kotlin נכנס אל src/production/res/ וכו'.
iOS: Targets ו-Schemes
ב-iOS, תפקיד ה-Flavors ממלא השילוב של Targets + Schemes + xcconfig. תיעוד המפתחים של Apple ממליץ על גישה זו להפרדת תצורות.
Target אחד, מספר Schemes + Build Configurations — עבור staging/production:
- צרו configurations: Debug, Staging, Release
- צרו Schemes: MyApp, MyApp-Staging
- כל Scheme מפעיל את ה-Configuration המתאים
מספר Targets — עבור white-label או גרסאות שונות מהותית (קוד שונה, יכולות שונות):
- לכל Target יש
src/dev/kotlin/, אייקון ו-Info.plist משלו - קוד משותף → Shared framework או קבצים משותפים שנוספו לשני ה-Targets
- כבד יותר לתחזוקה אך נותן שליטה מקסימלית
Targets: MyApp → com.myapp.ios → AppIcon → Release.xcconfig
MyApp-ClientB → com.clientb.myapp → AppIconClientB → ClientB.xcconfig
MyApp-Staging → com.myapp.ios.staging → AppIconStaging → Staging.xcconfig Flutter: Flavors
Flutter תומך ב-flavors באופן טבעי, וממפה אותם ל-Android Product Flavors ול-iOS Schemes מתחת למכסה המנוע:
flutter run --flavor staging -t lib/main_staging.dart flutter build apk --flavor production -t lib/main_production.dart PRODUCT_BUNDLE_IDENTIFIER מאתחל את האפליקציה עם תצורת staging, Targets: MyApp → com.myapp.ios → AppIcon → Release.xcconfig MyApp-ClientB → com.clientb.myapp → AppIconClientB → ClientB.xcconfig MyApp-Staging → com.myapp.ios.staging → AppIconStaging → Staging.xcconfig עם תצורת production. התצורה מועברת דרך flutter run --flavor staging -t lib/main_staging.dart flutter build apk --flavor production -t lib/main_production.dart או דרך main_staging.dart נפרד לכל flavor. ב-main_production.dart, ניתן להשתמש ב---dart-define כדי לייצר boilerplate—יצירת Targets/Schemes נדרשים ב-iOS ו-Product Flavors באנדרואיד מקובץ תצורה אחד.
מה לבחור: Target אחד או מספר?
התשובה תלויה בהיקף ההבדלים. אם מדובר רק ב-bundle ID, נקודת קצה API ואייקון—Target אחד עם מספר Schemes מספיק. אם יש צורך בקוד שונה, יכולות push (APNs/FCM) או SDKs של צד שלישי—לכו על מספר Targets (iOS) / flavorDimensions (אנדרואיד). באנדרואיד, flavorDimensions משלבים בקלות גרסה חינמית לעומת בתשלום ו-staging לעומת production בו-זמנית. לפי המדידות שלנו, Target אחד עם מספר Schemes מהיר פי 3 להגדרה מאשר מספר Targets.
מדוע הפרדת תצורות חוסכת זמן וכאבי ראש?
דמיינו ש-QA שבודק build של staging מוחק בטעות את מסד הנתונים של production? עם bundle IDs שונים זה בלתי אפשרי—המערכת מתייחסת אליהם כאפליקציות נפרדות. גרסת Dev יושבת לצד production, וניתן להשוות התנהגות באופן מיידי. בנוסף, הנחיות סקירת ה-App Store (סעיף 4.2) דורשות שגרסאות בדיקה לא יתערבבו עם גרסאות production—אנו לוקחים זאת בחשבון.
דוגמה מהפרקטיקה: white-label לרשת בתי קפה
הגדרנו 4 מותגים עם אייקונים, צבעים ומפתח API גיאוגרפי שונים. השתמשנו ב-2 flavorDimensions (מותג, סביבה) באנדרואיד וב-4 Targets ב-iOS. ה-CI בנה את הגרסה תוך 3 ימים. חיסכון בזמן בכל עדכון: 40%.טעויות אופייניות בהגדרת Flavors
| טעות | השלכה | פתרון |
|---|---|---|
| Flavor חדש ללא עדכון CI | ה-build לא יופיע ב-pipeline | הוסיפו lane ב-Fastlane |
| שכפול קוד | יכולת תחזוקה מופחתת | השתמשו בשכבת src/<flavor>/ |
| versionCode שונה בין אותם flavors | בלבול בגרסאות | רכזו את ניהול הגרסאות |
תהליך העבודה
- סקירת דרישות (כמה וריאנטים, מה ההבדלים, מי יבנה)
- בחירת גישה: Flavors לעומת Targets לעומת שילוב
- יצירת מבנה משאבים וקוד (שכבות משאבים, קבצי תצורה)
- הגדרת CI (Fastlane + GitHub Actions / GitLab CI) לבניית כל הווריאנטים
- בדיקת התקנה זו לצד זו (אימות שאין חפיפה בשמות חבילות)
- תיעוד התהליך להוספת גרסה חדשה
השוואת פלטפורמות
| קריטריון | אנדרואיד (Product Flavors) | iOS (Targets + Schemes) |
|---|---|---|
| מורכבות הגדרה | נמוכה (באמצעות Gradle) | בינונית (באמצעות Xcode Project) |
| תמיכה במספר גרסאות | מצוינת (flavorDimensions) | טובה (Targets דורשים סנכרון) |
| White-label (מותגים שונים) | קל (משאבים שונים בתיקיות) | כבד יותר (נדרש Shared framework) |
| אינטגרציית CI/CD | פשוטה (משימת Gradle) | בינונית (Fastlane + xcodebuild) |
| סקירת App Store | לא נדרשת | תשומת לב נפרדת לכל Target |
לוח זמנים ועלות
לוח זמנים: 2–3 ימים עבור scheme סטנדרטי (staging/production), עד 5 ימים עבור white-label עם מספר מותגים. העלות מחושבת באופן אישי לאחר סקירה. קבלו ייעוץ—צרו קשר, נעריך את הפרויקט שלכם ונציע את הפתרון האופטימלי.
הזמינו הגדרת flavor turnkey—הפרויקט שלכם יהיה מוכן לסקיילינג ללא קונפליקטים ארכיטקטוניים.







