# 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, if you omit a value entirely, it
will be assumed to be true. For example, this is the same as the
example above:

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

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