# Setting Flutter Android engine flags You can set flags for the Flutter engine on Android in two different ways: - From the command line when launching an app with the Flutter tool - Via `AndroidManifest.xml` metadata (static, per-build configuration) All flags available on Android can be set via the command line **and** via manifest metadata. See `src/flutter/shell/common/switches.cc` for the list of all supported flags, and see `src/flutter/shell/platform/android/io/flutter/embedding/engine/` `FlutterShellArgs.java` for the list of flags that can be set for the Android shell. ## When to use manifest metadata versus the command line Use the manifest when: - You want a fixed, reproducible baseline of engine flags for your app across all launches. This is ideal for CI and for enforcing a consistent configuration for your app. - You want to vary flags by build mode or product flavor via manifest merging. For example, place metadata in `src/debug/AndroidManifest.xml`, `src/profile/AndroidManifest.xml`, and `src/release/AndroidManifest.xml` (or per-flavor manifests) to tailor flags per variant. Use the command line when: - You want to quickly experiment with a flag for a single run of your app. - You need to override a flag that is already set in the manifest temporarily for debugging or testing purposes. **Note: If a flag is specified both on the command line and in the manifest, the command-line value takes precedence at runtime.** See below for details on using each method. ## How to set engine flags from the command line When you run a standalone Flutter app with the Flutter tool, engine flags can be passed directly and are forwarded to the Android engine. Examples: ```bash flutter run --trace-startup \ --enable-software-rendering \ --dart-flags="--enable-asserts" ``` Notes: - Flags that take values use the `--flag=value` form (with `=`). The Flutter tool forwards them in that form to the Android embedding. ## How to set engine flags in the manifest All manifest metadata keys must be prefixed with the package name `io.flutter.embedding.android` and are suffixed with the metadata name for the related command line flag as determined in `src/flutter/shell/platform/android/io/flutter/embedding/engine/` `FlutterShellArgs.java`. For example, the `--impeller-lazy-shader-mode=` command line flag corresponds to the metadata key `io.flutter.embedding.android.ImpellerLazyShaderInitialization`. For flags that take values, set the numeric, string, or boolean value (without the leading `--flag=` prefix). ### Examples Set the `--old-gen-heap-size=` flag to 322 MB: ```xml ... ``` Set the `--enable-flutter-gpu` flag: ```xml ``` ## Release-mode restrictions - Some flags are not allowed in release mode. The Android embedding enforces this policy (see `src/flutter/shell/platform/android/io/flutter/ embedding/engine/FlutterShellArgs`, which marks allowed flags with `allowedInRelease`). If a disallowed flag is set in release, it will be ignored. - If you need different behavior in release vs debug/profile mode, configure it via variant-specific manifests or product flavors. ## How to set engine flags dynamically As of the writing of this document, setting Flutter shell arguments via an Android `Intent` is no longer supported. If you need per-launch or runtime-controlled flags in an add-to-app integration, you may do so programatically before engine initialization. To do that, supply engine arguments directly to a `FlutterEngine` with the desired flags from the earliest point you can control in your application. For example, if you are writing an add-to-app app that launches a `FlutterActivity` or `FlutterFragment`, then you can cache a `FlutterEngine` that is initialized with your desired engine flags: ```kotlin // Your native Android application class MyApp : Application() { override fun onCreate() { super.onCreate() // Initialize the Flutter engine with desired flags val args = arrayOf( "--trace-startup", "--old-gen-heap-size=256", "--enable-software-rendering" ) val flutterEngine = FlutterEngine(this, args) // Start executing Dart code in the FlutterEngine flutterEngine.dartExecutor.executeDartEntrypoint( DartEntrypoint.createDefault() ) // Store the engine in the cache for later use FlutterEngineCache.getInstance().put("my_engine_id", flutterEngine) } } ``` Then, your `Activity` can launch a `FlutterActivity` or `FlutterFragment` with that cached `FlutterEngine`: ```kotlin // Start a FlutterActivity using the cached engine... val intent = FlutterActivity.withCachedEngine("my_engine_id").build(this) startActivity(intent) // Or launch a FlutterFragment using the cached engine val flutterFragment = FlutterFragment.withCachedEngine("my_engine_id").build() supportFragmentManager .beginTransaction() .add(R.id.fragment_container, flutterFragment, TAG_FLUTTER_FRAGMENT) .commit() ``` For a normal Flutter Android app, you can create and initialize a `FlutterEngine` with your desired flags the same as in the example above, then override `provideFlutterEngine` in your app's `FlutterActivity` to provide the configured `FlutterEngine`. For example: ```kotlin // Your Flutter Android application class MyApplication : FlutterApplication() { override fun onCreate() { super.onCreate() val args = arrayOf( "--trace-startup", "--old-gen-heap-size=256", "--enable-software-rendering" ) val flutterEngine = FlutterEngine(this, args) flutterEngine.dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) FlutterEngineCache .getInstance() .put(MY_ENGINE_ID, flutterEngine) } } // Your Flutter Android Activity class MainActivity: FlutterActivity() { override fun provideFlutterEngine(context: Context): FlutterEngine? { return FlutterEngineCache .getInstance() .get(MyApplication.MY_ENGINE_ID) } } ```