# 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)

Flags available on Android may be set via the command line **and/or** via
manifest metadata depending on the flag. See
`src/flutter/shell/platform/android/io/flutter/embedding/engine/`
`FlutterEngineFlags.java` for the list of flags that can be set for
the Android shell, and see  `src/flutter/shell/common/switch_defs.h`
for the list of all supported flags.

For flags that can be set on the command line and via the manifest,
see below to determine which method to use.

## 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/`
`FlutterEngineFlags.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 `--trace-to-file=` flag to `some_file.txt`:

```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application ...>
        <meta-data
            android:name="io.flutter.embedding.android.TraceToFile"
            android:value="some_file.txt"/>
            ...
    </application>
</manifest>
```

Set the `--enable-flutter-gpu` flag:

```xml
<meta-data
    android:name="io.flutter.embedding.android.EnableFlutterGPU"
    android:value=true
/>
```

For flags that take boolean values, you must explicitly set
`android:value="true"` to enable the flag. Omitting the value or
providing a non-boolean value (e.g., a typo like `"Fasle"`) will
default to `false` (disabled).

## 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/FlutterEngineFlags`, 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",
            "--trace-to-file=some_file.txt",
            "--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",
            "--trace-to-file=some_file.txt",
            "--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)
    }
}
```
