Skip to content

Commit 27be9f7

Browse files
authored
Merge pull request #406 from FlutterFlow/feature/config-files-build-gradle
Configuration Files : add details for build.gradle and AppDelegate.swift file
2 parents 011a53d + 7c79e3c commit 27be9f7

File tree

1 file changed

+192
-77
lines changed

1 file changed

+192
-77
lines changed

docs/ff-concepts/adding-customization/configuration-files.md

Lines changed: 192 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ In some cases, you’ll need to tweak the configuration files that FlutterFlow g
1616
Here are the key configuration files you can edit:
1717

1818
- [**`AndroidManifest.xml`**](#androidmanifestxml-android) – Configures app permissions, metadata, and intent filters for Android.
19+
- [**`build.gradle`**](#buildgradle-android) – Defines Android specific build configurations such as compile SDK version, dependencies, build types, and signing configurations.
20+
- [**ProGuard files**](#proguard-file-android) – Used for code shrinking and obfuscation in Android builds.
1921
- [**`Info.plist`**](#infoplist-ios)– Manages iOS app settings, including permissions and configurations.
2022
- [**`Entitlements.plist`**](#entitlementsplist-ios) – Defines iOS app privileges such as push notifications and Apple Pay.
23+
- [**`AppDelegate.swift`**](#appdelegateswift-ios) – Manages iOS app launch behavior and runtime configuration. It registers Flutter plugins, initializes services like Firebase, and handles app lifecycle events and deep linking.
2124
- [**`main.dart`**](#maindart-flutter) – The entry point of your Flutter app, where you can modify app-level logic.
22-
- [**ProGuard files**](#proguard-file-android) – Used for code shrinking and obfuscation in Android builds.
25+
2326

2427
:::warning
2528

@@ -29,17 +32,17 @@ In short, edit native code only when necessary, and do so carefully.
2932

3033
:::
3134

32-
## Editing native XML Files (AndroidManifest.xml, Info.plist, Entitlements.plist)
35+
## Editing Files
3336

34-
FlutterFlow provides two main ways to modify native XML files: [**Add Individual Snippets**](#option-1-add-individual-snippets) and [**Manual Edit Mode**](#option-2-manual-edit-mode).
37+
FlutterFlow provides two main ways to modify native files: [**Add Individual Snippets**](#option-1-add-individual-snippets) and [**Manual Edit Mode**](#option-2-manual-edit-mode).
3538

3639
### Option 1: Add Individual Snippets
3740

3841
**Snippets** are small pieces of code that you can inject into the native files at predefined locations. Instead of opening the whole file to edit, you provide just the fragment you want to add, and FlutterFlow merges it into the file in the correct place. This is safer and easier for small additions such as a permission line or a meta-data tag.
3942

4043
#### Snippet Placement for Android
4144

42-
For Android, modifications are typically made in the `AndroidManifest.xml` file, where you can add the following tags:
45+
Let’s see how to add a snippet for the `AndroidManifest.xml` file, where you can add the following tags:
4346

4447
- **Activity Tags:** Inserts XML code inside the `MainActivity` block. This is typically used to add child XML elements within the MainActivity, such as `<intent-filter>` or `<meta-data>` to control aspects such as deep linking, theme application, or launch mode.
4548
- **Application Tags**: Used to inject properties or attributes directly on the `<application>` tag itself. For example, you can use this to set values such as `android:icon`, `android:label`, `android:allowBackup`.
@@ -75,9 +78,9 @@ To add a snippet to your `AndroidManifest.xml`, navigate to **Custom Code** from
7578

7679
#### Snippet Placement for iOS
7780

78-
For iOS, you can modify the `Info.plist` and `Entitlements.plist` files. There’s no nested application/activity structure like on Android. Instead, both files are dictionaries of key-value pairs. When you add a snippet, it’s placed directly under the root `<dict>` element of these plist files.
81+
For iOS, let’s see how to add a snippet for the `Info.plist` and `Entitlements.plist` files. There’s no nested application/activity structure like on Android. Instead, both files are dictionaries of key-value pairs. When you add a snippet, it’s placed directly under the root `<dict>` element of these plist files.
7982

80-
To add a snippet to native iOS files, navigate to **Custom Code** (from the left-side menu) > **Configuration Files**, and select the desired file (`Info.plist` or `Entitlements.plist`). Click the **plus** (+) button, provide a descriptive name (which will appear as a comment in the file), and paste your snippet code.
83+
To add a snippet to native iOS files, navigate to **Custom Code** (from the left-side menu) > **Configuration Files**, and select the desired file. Click the **plus** (+) button, provide a descriptive name (which will appear as a comment in the file), and paste your snippet code.
8184

8285
<div style={{
8386
position: 'relative',
@@ -396,6 +399,161 @@ If your app needs to communicate over HTTP (unencrypted) for testing or legacy r
396399
You can modify the `AndroidManifest.xml` file by either [**adding a snippet**](#snippet-placement-for-android) or [**editing it manually**](#option-2-manual-edit-mode).
397400
:::
398401

402+
### `build.gradle` (Android)
403+
404+
The `build.gradle` file is the main Gradle build script for your Android app module. It resides in the `android/app/` directory and controls how your Android app is compiled, packaged, and built. This file defines critical configuration such as:
405+
406+
- SDK versions (`compileSdkVersion`, `minSdkVersion`, `targetSdkVersion`)
407+
- Dependencies for third-party libraries
408+
- Build types (like debug vs. release)
409+
- Signing configurations for release builds
410+
- Kotlin and Flutter settings
411+
- MultiDex and ProGuard rules
412+
- Android packaging options
413+
414+
In short, the `build.gradle` file acts as the blueprint for how your Android app is built and prepared for distribution.
415+
416+
**Example 1: Changing SDK Versions**
417+
418+
To set which Android SDK your app compiles with, update the following section in `build.gradle`:
419+
420+
```jsx
421+
android {
422+
compileSdkVersion 33
423+
424+
defaultConfig {
425+
applicationId "com.example.myapp"
426+
minSdkVersion 21
427+
targetSdkVersion 33
428+
versionCode 1
429+
versionName "1.0"
430+
}
431+
}
432+
```
433+
434+
Use this when you want to upgrade to a newer Android API level or need compatibility with certain libraries.
435+
436+
437+
**Example 2: Adding Third-Party Libraries**
438+
439+
To use Android-specific libraries (such as Play Services or Jetpack), add them in the `dependencies` section:
440+
441+
```jsx
442+
dependencies {
443+
implementation 'com.google.android.gms:play-services-maps:18.1.0'
444+
implementation 'androidx.work:work-runtime:2.7.1'
445+
}
446+
```
447+
448+
Use this when integrating services like Google Maps, Firebase Messaging, or WorkManager.
449+
450+
451+
**Example 3: Adding ProGuard Rules for Release Build**
452+
453+
If your app uses ProGuard (code shrinking/obfuscation), you can define custom rules or reference a rules file:
454+
455+
```jsx
456+
android {
457+
buildTypes {
458+
release {
459+
minifyEnabled true
460+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
461+
}
462+
}
463+
}
464+
```
465+
466+
Use this to reduce APK size and protect code in production.
467+
468+
**Example 4: Enabling MultiDex for Large Apps**
469+
470+
If your app exceeds the 64K method limit (common when using many dependencies), enable MultiDex support:
471+
472+
```jsx
473+
defaultConfig {
474+
...
475+
multiDexEnabled true
476+
}
477+
```
478+
479+
Use this when your build fails with `Too many methods` errors or when integrating large libraries like Firebase.
480+
481+
:::tip
482+
You can modify the `build.gradle` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
483+
:::
484+
485+
### ProGuard File (Android)
486+
487+
The **ProGuard file (`proguard-rules.pro`)** is a configuration file used in Android projects to optimize, shrink, and obfuscate the app’s code. It helps reduce APK or AAB size, improves performance, and protects the app’s code from reverse engineering by making it difficult to decompile.
488+
489+
The ProGuard files allow you to specify rules to keep certain classes or methods (prevent them from being removed or renamed), or to tweak the obfuscation behavior. Located in the **`android/app/proguard-rules.pro`** directory of an Android project, the ProGuard rules are applied when code shrinking is enabled in a release build.
490+
491+
Here are some scenarios where you may need to modify the ProGuard file:
492+
493+
**Example 1: Preventing Issues with Third-Party Libraries**
494+
495+
ProGuard can obfuscate critical libraries, breaking their functionality. To prevent this, you need to keep specific classes used by the library.
496+
497+
```jsx
498+
# Firebase
499+
-keep class com.google.firebase.** { *; }
500+
501+
# Gson (JSON Serialization)
502+
-keep class com.google.gson.** { *; }
503+
-keepattributes *Annotation*
504+
```
505+
506+
This ensures that Firebase and Gson classes are not obfuscated, preventing serialization errors.
507+
508+
**Example 2: Debugging ProGuard Issues**
509+
510+
If your app crashes in release mode but works in debug mode, ProGuard might be removing important classes. To troubleshoot, you can add logging and keep rules.
511+
512+
```jsx
513+
-assumenosideeffects class android.util.Log {
514+
public static *** d(...);
515+
public static *** v(...);
516+
public static *** i(...);
517+
}
518+
```
519+
520+
This removes debug logs in release builds but retains them for troubleshooting.
521+
522+
**Example 3: Improving Security by Removing Debug Information**
523+
524+
Attackers can decompile APKs and view sensitive debug logs. To remove these debug logs, add:
525+
526+
```jsx
527+
-dontwarn android.util.Log
528+
```
529+
530+
531+
**Example 4: Keeping Native Libraries (JNI) Safe**
532+
533+
If your app uses native C/C++ libraries (JNI), ProGuard may mistakenly remove required components. To prevent this:
534+
535+
```jsx
536+
-keep class com.example.native.** { *; }
537+
-keepclassmembers class * {
538+
native <methods>;
539+
}
540+
```
541+
542+
This keeps all native methods intact.
543+
544+
**Example 5: Preventing Issues with Reflection-Based Code**
545+
546+
Some libraries rely on reflection to dynamically call methods, which ProGuard may remove.
547+
548+
```jsx
549+
-keep class * implements android.os.Parcelable { *; }
550+
-keepclassmembers class ** {
551+
@android.webkit.JavascriptInterface <methods>;
552+
}
553+
```
554+
555+
This ensures reflection-based code continues working.
556+
399557
### `Info.plist` (iOS)
400558

401559
`Info.plist` (Information Property List) is the configuration file for iOS apps. It’s a structured XML file that provides iOS with essential information about your app’s configuration and requirements.
@@ -535,6 +693,34 @@ This enables your app to create, manage, and present passes in Apple Wallet.
535693
You can modify the `Entitlements.plist` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
536694
:::
537695

696+
### `AppDelegate.swift` (iOS)
697+
698+
The `AppDelegate.swift` file is the entry point for your iOS application. It plays a crucial role in setting up your app’s runtime environment and handling app lifecycle events such as launching, backgrounding, and termination. This file is also where you register Flutter plugins and initialize SDKs like Firebase or Branch.
699+
700+
It’s located at: `ios/Runner/AppDelegate.swift`
701+
702+
**Example: Registering Custom iOS Plugins**
703+
704+
For custom native iOS plugins that aren’t auto-registered, you can manually register them inside `AppDelegate.swift`.
705+
706+
```jsx
707+
override func application(
708+
_ application: UIApplication,
709+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
710+
) -> Bool {
711+
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
712+
let myPlugin = CustomPlugin()
713+
myPlugin.register(with: controller)
714+
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
715+
}
716+
```
717+
718+
Use this for custom iOS integrations that require manual setup.
719+
720+
:::tip
721+
You can modify the `AppDelegate.swift` file by either [**adding a snippet**](#snippet-placement-for-ios) or [**editing it manually**](#option-2-manual-edit-mode).
722+
:::
723+
538724
### `main.dart` (Flutter)
539725
540726
The `main.dart` file is the entry point of every FlutterFlow app. It is the first file that runs when the app starts and is responsible for initializing the application, configuring dependencies, and defining the root widget. Located in the **`lib/`** directory, `main.dart` contains the `main()` function, which is required for every FlutterFlow app.
@@ -642,77 +828,6 @@ class AppLifecycleObserver with WidgetsBindingObserver {
642828
}
643829
```
644830
645-
### ProGuard File (Android)
646-
647-
The **ProGuard file (`proguard-rules.pro`)** is a configuration file used in Android projects to optimize, shrink, and obfuscate the app’s code. It helps reduce APK or AAB size, improves performance, and protects the app’s code from reverse engineering by making it difficult to decompile.
648-
649-
The ProGuard files allow you to specify rules to keep certain classes or methods (prevent them from being removed or renamed), or to tweak the obfuscation behavior. Located in the **`android/app/proguard-rules.pro`** directory of an Android project, the ProGuard rules are applied when code shrinking is enabled in a release build.
650-
651-
Here are some scenarios where you may need to modify the ProGuard file:
652-
653-
**Example 1: Preventing Issues with Third-Party Libraries**
654-
655-
ProGuard can obfuscate critical libraries, breaking their functionality. To prevent this, you need to keep specific classes used by the library.
656-
657-
```jsx
658-
# Firebase
659-
-keep class com.google.firebase.** { *; }
660-
661-
# Gson (JSON Serialization)
662-
-keep class com.google.gson.** { *; }
663-
-keepattributes *Annotation*
664-
```
665-
666-
This ensures that Firebase and Gson classes are not obfuscated, preventing serialization errors.
667-
668-
**Example 2: Debugging ProGuard Issues**
669-
670-
If your app crashes in release mode but works in debug mode, ProGuard might be removing important classes. To troubleshoot, you can add logging and keep rules.
671-
672-
```jsx
673-
-assumenosideeffects class android.util.Log {
674-
public static *** d(...);
675-
public static *** v(...);
676-
public static *** i(...);
677-
}
678-
```
679-
680-
This removes debug logs in release builds but retains them for troubleshooting.
681-
682-
**Example 3: Improving Security by Removing Debug Information**
683-
684-
Attackers can decompile APKs and view sensitive debug logs. To remove these debug logs, add:
685-
686-
```jsx
687-
-dontwarn android.util.Log
688-
```
689-
690-
691-
**Example 4: Keeping Native Libraries (JNI) Safe**
692-
693-
If your app uses native C/C++ libraries (JNI), ProGuard may mistakenly remove required components. To prevent this:
694-
695-
```jsx
696-
-keep class com.example.native.** { *; }
697-
-keepclassmembers class * {
698-
native <methods>;
699-
}
700-
```
701-
702-
This keeps all native methods intact.
703-
704-
**Example 5: Preventing Issues with Reflection-Based Code**
705-
706-
Some libraries rely on reflection to dynamically call methods, which ProGuard may remove.
707-
708-
```jsx
709-
-keep class * implements android.os.Parcelable { *; }
710-
-keepclassmembers class ** {
711-
@android.webkit.JavascriptInterface <methods>;
712-
}
713-
```
714-
715-
This ensures reflection-based code continues working.
716831
717832
## Best Practices
718833

0 commit comments

Comments
 (0)