Перейти к основному содержимому

Файлы конфигурации

FlutterFlow позволяет изменять файлы конфигурации вашего приложения и файлы, специфичные для платформ, не выходя из интерфейса FlutterFlow.

В некоторых случаях вам потребуется внести корректировки в файлы конфигурации, которые генерирует FlutterFlow. Обычно это необходимо при интеграции сторонних пакетов, таких как аналитика, рекламные сети и платежные решения.

Вот ключевые файлы конфигурации, которые вы можете редактировать:

  • AndroidManifest.xml — Настраивает разрешения приложения, метаданные и фильтры интентов для Android.
  • build.gradle — Определяет конфигурации сборки, специфичные для Android, такие как версия compile SDK, зависимости, типы сборки и конфигурации подписи.
  • ProGuard files — Используются для сжатия и обфускации кода в сборках Android.
  • Info.plist — Управляет настройками приложения для iOS, включая разрешения и конфигурации.
  • Entitlements.plist — Определяет привилегии приложения для iOS, такие как push-уведомления и Apple Pay.
  • AppDelegate.swift — Управляет поведением запуска приложения для iOS и конфигурацией во время выполнения. Здесь регистрируются плагины Flutter, инициализируются сервисы вроде Firebase, а также обрабатываются события жизненного цикла приложения и глубокие ссылки.
  • main.dart — Точка входа в ваше приложение Flutter, где можно изменить логику на уровне приложения.
warning

Хотя редактирование файлов конфигурации позволяет разблокировать расширенный функционал, это сопряжено с рисками. Небольшая ошибка (например, пропущенный тег XML или неверный ключ) может привести к сбою компиляции или аварийному завершению приложения во время выполнения. Неправильные изменения могут вызвать отклонение приложения в App Store или Play Store. Поэтому важно фиксировать свои изменения и тщательно тестировать приложение после каждого редактирования.

Вкратце, редактируйте нативный код только при необходимости и делайте это осторожно.

Редактирование файлов

FlutterFlow предоставляет два основных способа изменения нативных файлов: Добавление отдельных фрагментов и Режим ручного редактирования.

Вариант 1: Добавление отдельных фрагментов

Фрагменты — это небольшие фрагменты кода, которые вы можете вставить в нативные файлы в предопределенных местах. Вместо открытия всего файла для редактирования вы предоставляете только фрагмент, который хотите добавить, а FlutterFlow объединяет его с файлом в правильном месте. Это безопаснее и проще для небольших добавлений, таких как строка разрешения или тег метаданных.

Размещение фрагментов для Android

Давайте разберем, как добавить фрагмент для файла AndroidManifest.xml, где можно добавить следующие теги:

  • Теги активности: Вставляет XML-код внутри блока MainActivity. Обычно это используется для добавления дочерних XML-элементов в MainActivity, таких как <intent-filter> или <meta-data>, чтобы управлять аспектами вроде глубоких ссылок, применения темы или режима запуска.
  • Теги приложения: Используется для вставки свойств или атрибутов непосредственно в тег <application>. Например, с помощью этого можно установить значения, такие как android:icon, android:label, android:allowBackup.
  • Теги компонентов приложения: Вставляет полные XML-компоненты внутри блока <application>...</application>. Используйте это для добавления дополнительных активностей, сервисов, широковещательных приемников или поставщиков контента, от которых зависит ваше приложение.

Чтобы добавить фрагмент в AndroidManifest.xml, перейдите в Custom Code из левого меню навигации, выберите Configuration Files, затем выберите AndroidManifest.xml. Нажмите кнопку plus (+) рядом с тегом, куда хотите вставить фрагмент. Укажите имя (оно будет включено как комментарий в файл) и вставьте код фрагмента.

Размещение фрагментов для iOS

Для iOS разберем, как добавить фрагмент для файлов Info.plist и Entitlements.plist. В отличие от Android, здесь нет вложенной структуры приложения/активности. Вместо этого оба файла представляют собой словари пар ключ-значение. При добавлении фрагмента он размещается непосредственно под корневым элементом <dict> этих файлов plist.

Чтобы добавить фрагмент в нативные файлы iOS, перейдите в Custom Code (из бокового меню) > Configuration Files и выберите нужный файл. Нажмите кнопку plus (+), укажите описательное имя (оно появится как комментарий в файле) и вставьте код фрагмента.

подсказка

Вариант 2: Режим ручного редактирования

Для более сложных изменений можно включить Режим ручного редактирования, который разблокирует весь файл для свободного редактирования. Это похоже на открытие сырого файла в текстовом редакторе непосредственно в FlutterFlow. Обратите внимание, что ручной режим мощный, но его следует использовать с осторожностью.

Чтобы вручную редактировать нативные файлы, перейдите в Custom Code (из бокового меню) > Configuration Files, выберите файл для редактирования и нажмите кнопку lock, чтобы разблокировать его. Теперь вы можете свободно изменять файл.

warning

После разблокировки файл остается в режиме ручного редактирования, пока вы не заблокируете его снова. Повторная блокировка сбросит файл к версии, сгенерированной FlutterFlow, что перезапишет все ручные изменения.

подсказка
  • Не удаляйте существующие записи FlutterFlow, если не уверены в этом. Безопаснее добавлять или изменять только необходимые строки, оставляя остальное как есть.
  • Используйте режим ручного редактирования для массовых или сложных правок, которые сложно выполнить с помощью фрагмента, например, для перестановки тегов, удаления чего-либо или вставки большого блока конфигурации. Всегда проверяйте, что приложение все еще собирается и запускается после таких правок.
  • Вы также можете использовать значения вашей среды разработки Environment Values и Library Values внутри фрагментов. Подробнее см. раздел Включение переменных в нативный код.

Включение переменных в нативный код

При редактировании нативных файлов в FlutterFlow вам может потребоваться включить динамические значения, такие как ключи API, конфигурации приложения или настройки, специфичные для среды. Вместо жесткого кодирования этих значений непосредственно в AndroidManifest.xml, Info.plist или других нативных файлах вы можете использовать значения среды FlutterFlow Environment Values и Library Values, чтобы сохранить гибкость и безопасность вашего приложения.

Чтобы включить переменную в файл конфигурации, сначала создайте переменную на уровне файла и присвойте ей значение из Environment Values или Library Values. Затем сослаться на эту переменную с помощью формата плейсхолдера (например, {{apiToken}}) внутри файла конфигурации. Эти плейсхолдеры в нативных файлах автоматически заменяются на реальные значения в процессе генерации кода.

Вот как это сделать шаг за шагом:

Вы также можете напрямую вставить плейсхолдер переменной (например, {{variableName}}) в код с помощью фрагмента или режима ручного редактирования, и FlutterFlow автоматически создаст соответствующую переменную на уровне файла.

подсказка

Вы можете использовать переменную на уровне файла в разных фрагментах внутри одного и того же файла.

Вот несколько примеров использования переменных в нативном коде:

Пример 1: Использование ключей API в AndroidManifest.xml

Предположим, вы интегрируете пакет Mapbox в приложение FlutterFlow, и для этого требуется ключ API в виде токена внутри файла AndroidManifest.xml. Вместо жесткого кодирования токена вы можете использовать переменную следующим образом:

<meta-data
android:name="com.mapbox.token"
android:value="{{MAPBOX_ACCESS_TOKEN}}"/>

Здесь {{MAPBOX_ACCESS_TOKEN}} — это переменная на уровне файла, которая содержит значение среды.

Пример 2: Настройка Info.plist для iOS

Для приложений iOS может потребоваться настройка App Transport Security (ATS), чтобы разрешить не-HTTPS-соединения. Вместо ручной установки NSAllowsArbitraryLoads в true вы можете использовать переменную:

<key>NSAllowsArbitraryLoads</key>
<{{ALLOW_HTTP_TRAFFIC}}/>

Если ALLOW_HTTP_TRAFFIC установлено в true в значении среды FlutterFlow, приложение разрешит HTTP-соединения.

Пример 3: Использование значений библиотеки

Если вы создаете библиотеку FlutterFlow и вам нужно включить публичные ключи API в нативный код, вы можете использовать Library Values в качестве плейсхолдеров. Это гарантирует, что при установке библиотеки пользователи смогут определить свои собственные значения.

Например, если ваша библиотека интегрируется с публичным API погоды, требующим ключ API (например, Open-Meteo или WeatherAPI для общего использования), лучше не добавлять ключ напрямую в файл манифеста. Вместо этого создайте переменную на уровне файла и присвойте ей значение библиотеки.

<application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="{{WEATHER_API_KEY}}" />
</application>

Пользователь библиотеки определит свой ключ API в Library Values при импорте вашей библиотеки. Во время сборки FlutterFlow заменит {{WEATHER_API_KEY}} на ключ, определенный пользователем.

Редактируемые файлы

FlutterFlow позволяет редактировать несколько ключевых нативных файлов. Ниже мы разберем роль каждого файла, причины, по которым может потребоваться его редактирование, и примеры реальных сценариев использования.

AndroidManifest.xml (Android)

AndroidManifest.xml — это основной файл конфигурации для вашего приложения Android. Он расположен в корневой директории папки android/app/src/main приложения и объявляет важную информацию о приложении для ОС Android и Google Play. Сюда входит имя пакета приложения, компоненты (активности, сервисы, приемники) и необходимые разрешения.

Он определяет аппаратные и программные возможности, от которых зависит приложение, такие как Bluetooth, GPS или датчики. Манифест управляет интентами и фильтрами, определяя, как приложение реагирует на системные события и глубокие ссылки. Он также включает метаданные и конфигурацию для SDK и библиотек, такие как ключи API или флаги функций.

Вкратце, манифест — это как удостоверение личности и лист разрешений для приложения в Android.

Вот несколько сценариев, где может потребоваться изменение файла AndroidManifest.xml:

Пример 1: Объявление компонентов приложения (активностей, сервисов, приемников)

Для включения дополнительных экранов (активностей), фоновых процессов (сервисов) или слушателей (широковещательных приемников) их нужно объявить в AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">

<!-- Add your activity here -->
<activity android:name=".NewScreenActivity" />

</application>

</manifest>

Это регистрирует NewScreenActivity, чтобы система знала о его существовании.

Пример 2: Запрос разрешений

Если ваше приложение требует доступа к ограниченным ресурсам, таким как wake locks (для поддержания активности устройства) или запись аудио, необходимо объявить соответствующие разрешения в AndroidManifest.xml путем ручного редактирования файла. Совет: Вы также можете добавлять пользовательские разрешения напрямую через Permission Settings в FlutterFlow.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourappname">

<!-- Permissions -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

<application
android:label=""
tools:replace="android:label"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">

<activity android:name=".NewScreenActivity"/>

</application>
</manifest>

Без этих разрешений приложение не сможет поддерживать активность устройства или записывать аудио.

Пример 3: Добавление метаданных для SDK и библиотек

Многие сторонние пакеты (Google Maps, Firebase, AdMob и т. д.) требуют тег <meta-data> в AndroidManifest.xml для передачи конфигурационных значений. Например, плагин Mapbox Flutter требует добавления токена доступа Mapbox в качестве записи метаданных для инициализации. Реальный пример: для инициализации Mapbox добавьте:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">

<!-- Your snippet goes here -->
<meta-data
android:name="com.example.MAPS_API_KEY"
android:value="YOUR_API_KEY" />

</application>
</manifest>

Пример 4: Ограничение приложения определенными устройствами

Вы можете указать требования к аппаратному обеспечению устройства (например, GPS, камера, сенсорный экран), чтобы приложение устанавливалось только на совместимых устройствах.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<!-- Your snippet goes here -->
<uses-feature android:name="android.hardware.camera" />

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">

<!-- other components -->

</application>

</manifest>

Это предотвращает установку на устройствах без камеры.

Пример 5: Разрешение трафика в открытом виде

Если ваше приложение должно общаться по HTTP (нешифрованному) для тестирования или по причинам совместимости со старыми версиями, может потребоваться добавить android:usesCleartextTraffic="true" в тег <application>. Это ослабляет сетевую безопасность для HTTP-URL.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true"> <!-- Add this line -->

<!-- Other components -->

</application>

</manifest>
подсказка

Вы можете изменить файл AndroidManifest.xml либо добавив фрагмент, либо отредактировав его вручную.

build.gradle (Android)

Файл build.gradle — это основной скрипт сборки Gradle для модуля вашего приложения Android. Он находится в директории android/app/ и управляет тем, как компилируется, упаковывается и собирается ваше приложение Android. Этот файл определяет ключевые конфигурации, такие как:

  • Версии SDK (compileSdkVersion, minSdkVersion, targetSdkVersion)
  • Зависимости для сторонних библиотек
  • Типы сборки (например, debug против release)
  • Конфигурации подписи для сборок релиза
  • Настройки Kotlin и Flutter
  • Правила MultiDex и ProGuard
  • Опции упаковки Android

Вкратце, файл build.gradle служит чертежом для сборки и подготовки вашего приложения Android к распространению.

Пример 1: Изменение версий SDK

Чтобы указать, с каким Android SDK компилируется ваше приложение, обновите следующий раздел в build.gradle:

android {
compileSdkVersion 33

defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName "1.0"
}
}

Используйте это при обновлении до нового уровня API Android или для совместимости с определенными библиотеками.

Пример 2: Добавление сторонних библиотек

Чтобы использовать библиотеки, специфичные для Android (например, Play Services или Jetpack), добавьте их в раздел dependencies:

dependencies {
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'androidx.work:work-runtime:2.7.1'
}

Используйте это при интеграции сервисов вроде Google Maps, Firebase Messaging или WorkManager.

Пример 3: Добавление правил ProGuard для сборки релиза

Если ваше приложение использует ProGuard (сжатие/обфускация кода), вы можете определить пользовательские правила или сослаться на файл правил:

android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

Используйте это для уменьшения размера APK и защиты кода в продакшене.

Пример 4: Включение MultiDex для больших приложений

Если ваше приложение превышает лимит в 64K методов (что часто бывает при использовании множества зависимостей), включите поддержку MultiDex:

defaultConfig {
...
multiDexEnabled true
}

Используйте это, когда сборка завершается ошибкой Too many methods или при интеграции больших библиотек вроде Firebase.

подсказка

Вы можете изменить файл build.gradle либо добавив фрагмент, либо отредактировав его вручную.

ProGuard File (Android)

Файл ProGuard (proguard-rules.pro) — это файл конфигурации, используемый в проектах Android для оптимизации, сжатия и обфускации кода приложения. Он помогает уменьшить размер APK или AAB, улучшить производительность и защитить код приложения от обратной инженерии, затрудняя декомпиляцию.

Файлы ProGuard позволяют указывать правила для сохранения определенных классов или методов (чтобы предотвратить их удаление или переименование) или для настройки поведения обфускации. Они расположены в директории android/app/proguard-rules.pro проекта Android, и правила ProGuard применяются при включенном сжатии кода в сборке релиза.

Вот несколько сценариев, где может потребоваться изменение файла ProGuard:

Пример 1: Предотвращение проблем со сторонними библиотеками

ProGuard может обфусцировать критические библиотеки, нарушая их функциональность. Чтобы предотвратить это, нужно сохранить конкретные классы, используемые библиотекой.

# Firebase
-keep class com.google.firebase.** { *; }

# Gson (JSON Serialization)
-keep class com.google.gson.** { *; }
-keepattributes *Annotation*

Это гарантирует, что классы Firebase и Gson не будут обфусцированы, предотвращая ошибки сериализации.

Пример 2: Отладка проблем ProGuard

Если ваше приложение падает в режиме релиза, но работает в режиме отладки, ProGuard может удалять важные классы. Для устранения неисправностей можно добавить логирование и правила сохранения.

-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}

Это удаляет отладочные логи в сборках релиза, но сохраняет их для устранения неисправностей.

Пример 3: Улучшение безопасности за счет удаления отладочной информации

Злоумышленники могут декомпилировать APK и просматривать чувствительные отладочные логи. Чтобы удалить эти логи, добавьте:

-dontwarn android.util.Log

Пример 4: Сохранение нативных библиотек (JNI) в безопасности

Если ваше приложение использует нативные библиотеки C/C++ (JNI), ProGuard может ошибочно удалить необходимые компоненты. Чтобы предотвратить это:

-keep class com.example.native.** { *; }
-keepclassmembers class * {
native <methods>;
}

Это сохраняет все нативные методы в неприкосновенности.

Пример 5: Предотвращение проблем с кодом на основе рефлексии

Некоторые библиотеки полагаются на рефлексию для динамического вызова методов, которые ProGuard может удалить.

-keep class * implements android.os.Parcelable { *; }
-keepclassmembers class ** {
@android.webkit.JavascriptInterface <methods>;
}

Это гарантирует, что код на основе рефлексии продолжит работать.

Info.plist (iOS)

Info.plist (Information Property List) — это файл конфигурации для приложений iOS. Это структурированный XML-файл, который предоставляет iOS важную информацию о конфигурации и требованиях вашего приложения.

Info.plist определяет такие вещи, как идентификатор пакета приложения, отображаемое имя, версию и, что самое важное, описания использования для разрешений и других настроек, необходимых iOS во время выполнения. Этот файл обязателен для каждого приложения iOS и расположен в директории /ios/Runner/ вашего приложения FlutterFlow.

По сути, это чертеж, который помогает iOS понять возможности и потребности вашего приложения.

Вот несколько сценариев, где может потребоваться изменение файла Info.plist:

Пример 1: Запрос разрешений

Если ваше приложение требует доступа к местоположению как во время использования, так и в фоновом режиме, необходимо объявить соответствующие разрешения в Info.plist. Совет: Вы также можете добавлять пользовательские разрешения напрямую через Permission Settings в FlutterFlow.

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires location access while in use to provide location-based services.</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app requires background location access to enable continuous location tracking.</string>

Это гарантирует, что приложение сможет получать доступ к службам геолокации, даже когда пользователь не активно им пользуется.

Пример 2: Включение App Transport Security (ATS) для HTTP-запросов

По умолчанию iOS требует HTTPS-соединения по соображениям безопасности. Если ваше приложение должно общаться с серверами, поддерживающими только HTTP, необходимо изменить Info.plist.

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

Это разрешает все HTTP-запросы, но использовать следует с осторожностью

Пример 3: Настройка фоновых режимов

Если ваше приложение требует фонового функционала (например, воспроизведение музыки, отслеживание местоположения), необходимо включить фоновые режимы в Info.plist.

<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>location</string>
</array>

Это позволяет приложению воспроизводить аудио или отслеживать местоположение при работе в фоновом режиме.

Пример 4: Добавление ключей

Многие сторонние пакеты требуют добавления ключей в файл Info.plist. Например, если вы используете SDK Mapbox, вам нужно предоставить токен доступа в Info.plist, чтобы включить функционал карт.

<key>io.flutter.embedded_views_preview</key>
<true/>
<key>MGLMapboxAccessToken</key>
<string>YOUR_MAPBOX_ACCESS_TOKEN</string>

Ключ MGLMapboxAccessToken требуется для инициализации карт Mapbox в вашем приложении. Кроме того, ключ io.flutter.embedded_views_preview должен быть установлен в true, чтобы поддерживать встраивание нативных представлений внутри виджетов Flutter.

подсказка

Вы можете изменить файл Info.plist либо добавив фрагмент, либо отредактировав его вручную.

Entitlements.plist (iOS)

Файл Entitlements.plist — это список свойств в приложениях iOS, который определяет возможности и разрешения, связанные с безопасностью приложения. Он предоставляет приложению конкретные привилегии, позволяя получать доступ к службам Apple, таким как iCloud, push-уведомления, группы приложений, фоновые режимы и доступ к хранилищу ключей. Он расположен в директории /ios/Runner/ вашего приложения FlutterFlow и называется Runner.entitlements.

Этот файл гарантирует, что только авторизованные приложения могут использовать эти функции, поддерживая безопасность и предотвращая несанкционированный доступ к чувствительным системным функциям.

Вот несколько сценариев, где может потребоваться изменение файла Entitlements.plist:

Пример 1: Включение хранения в iCloud

Если ваше приложение интегрируется с службами iCloud, такими как синхронизация пользовательских данных или хранение документов, необходимо добавить привилегии iCloud.

<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.yourcompany.appname</string>
</array>

<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
</array>

Это предоставляет приложению доступ к хранилищу iCloud в указанном контейнере.

Пример 2: Включение доступа к хранилищу ключей

Если ваше приложение должно хранить безопасные учетные данные, требуется включить совместное использование хранилища ключей.

<key>keychain-access-groups</key>
<array>
<string>com.yourcompany.appname</string>
</array>

Это позволяет безопасно хранить учетные данные для входа, токены API или ключи шифрования в хранилище ключей iOS.

Пример 3: Включение групп приложений для общих данных

Если ваше приложение обменивается данными между несколькими приложениями или расширением приложения (например, виджетом или Siri-шорткатом), необходимо включить группы приложений.

<key>com.apple.security.application-groups</key>
<array>
<string>group.com.yourcompany.shared</string>
</array>

Это позволяет разным приложениям или расширениям получать доступ к общему хранилищу и настройкам пользователя.

Пример 4: Включение Wallet (Apple Pay и пропуска)

Если ваше приложение интегрируется с Apple Wallet, необходимо добавить привилегии Wallet.

<key>com.apple.developer.pass-type-identifiers</key>
<array>
<string>pass.com.yourcompany.appname</string>
</array>

Это позволяет приложению создавать, управлять и отображать пропуска в Apple Wallet.

подсказка

Вы можете изменить файл Entitlements.plist либо добавив фрагмент, либо отредактировав его вручную.

AppDelegate.swift (iOS)

Файл AppDelegate.swift — это точка входа для вашего приложения iOS. Он играет ключевую роль в настройке среды выполнения приложения и обработке событий жизненного цикла, таких как запуск, переход в фон и завершение. В этом файле также регистрируются плагины Flutter и инициализируются SDK вроде Firebase или Branch.

Он расположен по пути: ios/Runner/AppDelegate.swift

Пример: Регистрация пользовательских плагинов iOS

Для пользовательских нативных плагинов iOS, которые не регистрируются автоматически, вы можете вручную зарегистрировать их внутри AppDelegate.swift.

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
let myPlugin = CustomPlugin()
myPlugin.register(with: controller)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

Используйте это для пользовательских интеграций iOS, требующих ручной настройки.

подсказка

Вы можете изменить файл AppDelegate.swift либо добавив фрагмент, либо отредактировав его вручную.

main.dart (Flutter)

Файл main.dart — это точка входа для каждого приложения FlutterFlow. Это первый файл, который запускается при старте приложения, и он отвечает за инициализацию приложения, настройку зависимостей и определение корневого виджета. Расположенный в директории lib/, main.dart содержит функцию main(), которая обязательна для каждого приложения FlutterFlow.

Если вам нужно выполнить любой пользовательский код Dart при запуске — например, инициализировать сторонние SDK, установить глобальные конфигурации, сервисы локаторов, вывести отладочный лог или запустить определенные функции один раз — main.dart — подходящее место для этого.

к сведению

Добавление фрагментов недоступно для main.dart. Вместо этого вы можете напрямую изменить файл с помощью Режима ручного редактирования.

Вот несколько сценариев, где может потребоваться изменение файла main.dart:

Пример 1: Инициализация сторонних пакетов

Многие пакеты имеют вызовы инициализации. Например, если вы добавили пользовательский пакет для аналитики или отслеживания ошибок (скажем, Sentry или сервис логирования), может потребоваться вызвать SentryFlutter.init() или настроить обработчик ошибок при запуске приложения. Разместив этот вызов в main.dart (до или сразу после runApp), вы гарантируете его раннее выполнение.

import 'dart:async';

import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

Future<void> main() async {
runZonedGuarded(() async {
await SentryFlutter.init(
(options) {
options.dsn = 'https://example@sentry.io/add-your-dsn-here';
},
);

runApp(MyApp());
}, (exception, stackTrace) async {
await Sentry.captureException(exception, stackTrace: stackTrace);
});
}

Это гарантирует, что Sentry готов до запуска приложения, как и инициализация Firebase.

Пример 2: Настройка внешнего вида строки состояния

Если вы хотите изменить цвет строки состояния и скорректировать яркость иконок для Android и iOS, необходимо изменить main.dart перед вызовом runApp().


import 'package:flutter/services.dart';

void main() {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Colors.redAccent, // Custom status bar color
statusBarIconBrightness: Brightness.dark, // Dark icons for Android
statusBarBrightness: Brightness.light, // Light icons for iOS
),
);

runApp(MyApp());
}

Пример 3: Блокировка ориентации экрана

Некоторым приложениям требуется только альбомная или только портретная ориентация. Вы можете принудительно установить ориентацию экрана в main.dart перед запуском приложения.

import 'package:flutter/services.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

await SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);

runApp(MyApp());
}

Это гарантирует, что приложение работает только в альбомном режиме.

Пример 4: Отслеживание изменений жизненного цикла приложения

Если ваше приложение должно реагировать на события жизненного цикла, такие как отслеживание перехода в фон или возвращение на передний план, вы можете прикрепить наблюдатель.

import 'package:flutter/widgets.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
WidgetsBinding.instance.addObserver(AppLifecycleObserver());
runApp(MyApp());
}

class AppLifecycleObserver with WidgetsBindingObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
print('App is in foreground');
} else if (state == AppLifecycleState.paused) {
print('App is in background');
}
}
}

Лучшие практики

  • Резервное копирование: Перед внесением изменений в нативные файлы убедитесь, что у вас есть резервная копия хотя бы текста исходного файла. Вы также можете закоммитить изменения, чтобы иметь возможность откатить их при необходимости. Таким образом, если что-то пойдет не так, вы сможете вручную восстановить.
  • Одно изменение за раз: Добавляйте или изменяйте по одному элементу за раз, а затем тестируйте приложение. Если вы добавите несколько вещей и что-то сломается, будет сложнее определить, какое именно изменение вызвало проблему.
  • Консультация документации пакетов: При внесении изменений для сторонних пакетов следуйте их инструкциям точно. Обычно документация пакетов показывает фрагмент — используйте его в фрагменте FlutterFlow. Дважды проверьте официальную документацию для Android или iOS, если не уверены в правильных ключах или тегах. Например, при включении фоновой загрузки документация Apple укажет точную строку для использования в Info.plist (fetch в массиве UIBackgroundModes).
  • Минимализм: Добавляйте только то, что действительно нужно. Не добавляйте множество привилегий или разрешений «на всякий случай», поскольку это может раздуть и усложнить приложение, а также вызвать проверку в магазинах на использование функций, которых в вашем приложении на самом деле нет.
  • Использование комментариев: При модификации файлов добавляйте к ним аннотации. Если через шесть месяцев вы или член команды посмотрите на манифест, комментарий вроде <!-- Added for Payments SDK on Feb 2025 --> окажется очень полезным.
  • Тестирование на устройствах: Особенно для всего, что связано с Info.plist или привилегиями, всегда тестируйте на реальном устройстве iOS, если это возможно. Некоторые проблемы (например, отсутствие привилегий или использование фонового режима) не проявятся в симуляторе. Аналогично, тестируйте изменения Android на устройстве или эмуляторе с сборкой релиза — поскольку эффекты правил ProGuard, например, проявляются только в режиме релиза.
  • Мониторинг логов и ошибок: После внесения изменений отслеживайте консоль Xcode или logcat Android при запуске приложения. При неправильных конфигурациях часто появляются предупреждения.
  • Следите за обновлениями: FlutterFlow может улучшать функции редактирования нативного кода со временем. Следите за документацией FlutterFlow или объявлениями сообщества. Если они введут новый, более простой способ, отдавайте предпочтение ему перед ручным редактированием, поскольку он будет более надежным.
  • Соображения безопасности: Помните, что все в этих файлах (особенно Info.plist, AndroidManifest.xml) по сути публично в распространяемом приложении. Не предполагайте, что ключ API в Info.plist скрыт — это не так. Для ключей, которые вы должны включить (карты и т. д.), рассмотрите использование приватных значений среды и мониторинг их использования.

FAQs

Мое приложение не устанавливается на устройстве iOS. Что проверить?

Убедитесь, что привилегии в Entitlements.plist соответствуют вашему профилю обеспечения. Если вы видите ошибку «Missing entitlement», это значит, что вы добавили привилегию, не разрешенную вашим профилем. Удалите ее или обновите профиль в Apple Developer Portal.

Как исправить «Manifest merger failed» на Android?

Эта ошибка указывает на конфликт в вашем AndroidManifest.xml. Распространенные проблемы включают дублирующиеся разрешения или атрибуты (например, две записи <application android:label>). Сообщение об ошибке обычно указывает на конфликтующую строку. Удалите дубликат или убедитесь, что каждое свойство установлено только один раз, чтобы разрешить конфликт.

Почему мое приложение не запускается в Test Mode после редактирования файла main.dart с включенным Supabase?

Существует известное ограничение, при котором редактирование файла main.dart с включенным Supabase предотвращает запуск Test Mode. В качестве обходного пути используйте Local Run для тестирования приложения.

Можно ли изменять файлы конфигурации в проекте библиотеки?

Да, можно. При импорте проекта библиотеки любые фрагменты файлов конфигурации, такие как для AndroidManifest.xml, Info.plist или Entitlements.plist, автоматически объединяются с файлами конфигурации импортирующего проекта.

Кроме того, ваш проект библиотеки может передавать значения (например, ключи API) в эти фрагменты с помощью Library Values, что упрощает настройку.

config-values-in-library

Это делает библиотеки невероятно мощными и позволяет легко интегрировать инструменты вроде PostHog (аналитика), Sentry (отчеты о сбоях), CleverTap, flutter_local_notifications, flutter_nfc_kit и многие другие напрямую из Marketplace.