Flutter Flavors: Полное руководство по нескольким средам в Android и iOS
FlutterPulseЭта статья переведена специально для канала FlutterPulse. В этом канале вы найдёте много интересных вещей, связанных с Flutter. Не забывайте подписываться! 🚀

Настройте флейворы Flutter для разработки, тестовой среды и продакшена с пользовательскими иконками, названиями и конфигурациями — всё из одного кода.
Флейворы — это нативные конфигурации, которые позволяют создавать несколько версий одного приложения из одного кода — каждая со своими иконками, названиями, конфигурациями и поведением.
Основная цель — изолировать разные среды — разработка (dev), тестирование (stg) и продакшен (prod) — чтобы тестирование, валидация и развертывание были более независимыми и организованными.
С флейворами вы можете устанавливать и тестировать несколько вариантов приложения на одном устройстве, распространять их через магазины приложений или платформы тестирования, такие как Firebase Distribution, и они могут существовать без перезаписи друг друга.
В этой статье я проведу вас через пошаговую настройку флейворов dev, stg и prod в приложении Flutter для Android и iOS.
Оглавление
Флейворы на AndroidФлейворы на iOSОтображение баннера флейвора в приложенииНастройка VSCode
Флейворы на Android
1. Настройте build.gradle
В вашем проекте Flutter откройте файл android/app/build.gradle и внутри блока android добавьте конфигурацию флейворов:
android {
...
flavorDimensions "env"
productFlavors {
stg {
dimension "env"
applicationIdSuffix ".stg"
versionNameSuffix "-stg"
resValue "string", "app_name", "App STG"
}
dev {
dimension "env"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
resValue "string", "app_name", "App DEV"
}
prod {
dimension "env"
resValue "string", "app_name", "App"
}
}
}applicationIdSuffix: Суффикс, добавляемый к идентификатору приложения. Приложение с идентификаторомcom.example.appсобранное с флейворомdevстановитсяcom.example.app.dev.resValue: Назначает уникальное название приложения для каждого флейвора.
Замените App, App DEV и App STG на соответствующее название для каждого флейвора вашего приложения.
2. Редактирование AndroidManifest
Откройте файл android/app/src/main/AndroidManifest.xml и обновите свойство android:label:
...
<application
android:label="@string/app_name"
Готово! Теперь ваше приложение имеет настроенные флейворы, и вы можете протестировать его, запустив:
flutter run --flavor dev
3. Создание иконок приложения
Теперь давайте создадим разные иконки для каждого флейвора.
В Android Studio откройте папку android.
Переключите режим просмотра на Project.

Внутри app/src, создайте следующие папки: dev/res и stg/res.

Щелкните правой кнопкой мыши по папке res, которую вы только что создали, и перейдите в New > Image Asset.

Импортируйте иконку, отрегулируйте её размер и сохраните.

Повторите этот процесс для каждого флейвора. Учтите, что иконки для флейвора prod остаются в папке по умолчанию main/res/.
Теперь, при запуске приложения на устройстве Android, каждый флейвор будет отображать свою иконку.

Флейворы на iOS
- Создайте схемы
Откройте файл ios/Runner.xcworkspace с помощью Xcode.
В верхнем меню перейдите в: Product -> Scheme -> Manage Schemes.

Нажмите кнопку + и создайте схемы dev и stg:

Переименуйте существующую схему Runner в prod.

Теперь, в левой панели, нажмите на Runner, и под PROJECT, выберите Runner снова. Перейдите на вкладку Info и нажмите кнопку + для добавления новой конфигурации сборки.

Вам нужно дублировать существующие конфигурации Debug, Release и Profile, создавая набор для каждого флейвора.

Переименуйте их в соответствии с каждым флейвором, например: Debug-prod, Release-dev, Profile-stg. В итоге результат будет таким:

Далее, вернитесь к Product -> Scheme -> Manage Schemes, выберите схему и нажмите Edit.

Для каждой схемы флейвора выберите соответствующие конфигурации сборки в левой боковой панели.
- Для
prod, выберите конфигурации, заканчивающиеся на-prod - Для
dev, используйте те, что заканчиваются на-dev - Для
stg, те, что заканчиваются на-stg

Повторите это для всех схем.
2. Редактирование bundle.id
Нажмите на Runner под TARGETS, затем перейдите в Build Settings. Поищите "bundle", чтобы найти раздел Packaging.
Добавьте соответствующий суффикс к Bundle Identifier для каждого флейвора:
.devдля разработки.stgдля staging- Оставьте без изменений для продакшена

После этого у каждого флейвора будет уникальный идентификатор, как в примере:

3. Изменить отображаемое имя приложения
Всё ещё внутри TARGETS → Runner, перейдите на вкладку Info. Измените значение Bundle display name на: $(APP_DISPLAY_NAME)

Теперь перейдите в Build Settings, нажмите + и выберите Add User-Defined Setting.

Определите одно значение для каждой сборки. В итоге настройка должна выглядеть примерно так:

Теперь вы можете запустить приложение с помощью: flutter run --flavor dev.
4. Создать иконки приложения
В iOS иконки приложения требуют нескольких размеров. Ручное их создание занимает много времени, поэтому вы можете использовать платформу AppIcon для упрощения процесса.
- Загрузите свою иконку
- Выберите iPhone (и iPad, если нужно)
- Скачайте сгенерированный zip-архив
Внутри скачанной папки скопируйте AppIcon.appiconset из AppIcons/Assets.xcassets.
Вставьте её в свой проект по адресу: ios/Runner/Assets.xcassets/

Переименуйте папку в соответствии с каждой сборкой:
AppIcon-dev.appiconsetAppIcon-stg.appiconset- Оставьте стандартное имя для
prod

Затем вернитесь в Xcode. Под TARGETS → Runner → Build Settings, найдите "primary". Вы найдёте настройку Primary App Icon Set Name.
Установите имя для каждой сборки (например, AppIcon-dev). Оставьте стандартное для prod.

Итоговый результат будет таким:

Теперь, когда вы запускаете приложение на iOS-симуляторе или устройстве, каждый флейвор будет отображать свой собственный значок.

Отображение баннера флейвора в приложении
Теперь мы покажем баннер внутри приложения, указывающий, запущено ли оно под флейвором dev или stg.
На данный момент у вас есть два варианта:
- Использовать один файл
main.dart, или - Использовать отдельные точки входа (
main_dev.dart,main_stg.dart, и т.д.)
Мы рассмотрим оба подхода.
- Одиночный файл
main.dart
В этом подходе мы передаем флейвор в приложение с помощью параметра --dart-define, как показано ниже:
flutter run --flavor dev --dart-define=FLAVOR=dev
Вот как будет выглядеть файл main.dart:
void main() {
const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'prod');
runApp(
const App(flavor: flavor),
);
}Теперь мы можем отображать баннер на основе текущего флейвора:
class App extends StatelessWidget {
const App({
super.key,
required this.flavor,
});
final String flavor;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
debugShowCheckedModeBanner: false,
home: flavor != 'prod'
? Banner(
message: flavor.toUpperCase(),
location: BannerLocation.topStart,
color: Color(0xFF2D808D),
child: const HomePage(),
)
: const HomePage(),
);
}
}Здесь мы применяем логику: если флейвор не prod, баннер будет отображаться.
2. Несколько файлов main.dart
В этом подходе мы оставляем файл main.dart в качестве точки входа для prod и создаем отдельные файлы для других флейворов, такие как main_dev.dart и main_stg.dart.
Каждый файл жестко закодирован для соответствующего флейвора:
void main() {
runApp(
const App(flavor: 'dev'),
);
}Для запуска приложения используйте:
flutter run --flavor dev -t lib/main_dev.dart.

Настройка VSCode
Чтобы отлаживать приложение с помощью VSCode с разными вариантами, необходимо правильно настроить файл launch.json.
Настройка зависит от того, используете ли вы один файл main.dart или отдельные точки входа для каждого варианта.
В вашем проекте откройте файл: .vscode/launch.json.
Если вы используете один файл main.dart:
{
"version": "0.2.0",
"configurations": [
{
"name": "App",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"prod",
]
},
{
"name": "App Dev",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"dev",
"--dart-define",
"FLAVOR=dev"
]
},
{
"name": "App Stg",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"stg",
"--dart-define"
"FLAVOR=stg"
]
}
]
}Или если вы используете несколько файлов main.dart:
{
"version": "0.2.0",
"configurations": [
{
"name": "App",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"prod",
]
},
{
"name": "App Dev",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"dev",
"-t",
"lib/main_dev.dart",
]
},
{
"name": "App Stg",
"request": "launch",
"type": "dart",
"args": [
"--flavor",
"stg",
"-t",
"lib/main_stg.dart",
]
}
]
}Теперь мы завершили полную настройку вариантов Flutter — мощной функции, которая позволяет изолировать различные среды, делая тестирование, проверку и развертывание более организованными и эффективными.
Хотя это нативная функция платформы, варианты работают плавно с Flutter при правильной настройке, позволяя гибридным приложениям в полной мере использовать эту возможность с помощью пользовательских иконок, имен, поведения и разделения сред.