Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
e15544b
Migrate the flutter-apk copy and per-ABI versionCode to the variant API
reidbaker-agent Oct 1, 2026
33f3987
Address review: stop reading versionCode, document APK transform fail…
reidbaker-agent Oct 2, 2026
8c9a54d
Unify add-to-app module wiring on the variant API
reidbaker-agent Oct 2, 2026
f668780
Address review: specific caching reason, shared APK error text, short…
reidbaker-agent Oct 2, 2026
2c28d8f
Merge branch 'agp-apk-copy-versioncode' of https://github.com/reidbak…
reidbaker-agent Oct 2, 2026
a6be160
Trim comments added by PR 8
reidbaker-agent Oct 2, 2026
b8cd39b
Address review: clarify the variant gate and task registration comments
reidbaker-agent Oct 5, 2026
2efbd34
Address review: check the add-to-app module in module_host_with_custo…
reidbaker-agent Oct 5, 2026
d8f869e
Address review: share task registration stubs in FlutterPluginTest
reidbaker-agent Oct 5, 2026
798ac29
Address review: take ApplicationVariant in configureApplicationOutputs
reidbaker-agent Oct 5, 2026
1366874
Address review: drop android.compatibility.enableLegacyApi from the q…
reidbaker-agent Oct 5, 2026
25550b3
Show the no-DSL-versionCode split-per-abi warning by default
reidbaker-agent Oct 7, 2026
eb20bbd
Merge commit '25550b3fc49884678289f023ae7b8df060049e33' into agp-add-…
reidbaker-agent Oct 7, 2026
23ddd6b
Merge branch 'master' of https://github.com/flutter/flutter into agp-…
reidbaker-agent Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions dev/devicelab/bin/tasks/module_host_with_custom_build_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,57 @@ Future<void> main() async {
'lib/armeabi-v7a/libflutter.so',
], await getFilesInApk(demoProdApk));

await clean();

section('Run app:assembleDemoQa with android.newDsl=true');

// The fixture's gradle.properties sets android.newDsl=false. With
// android.newDsl=true, AGP has no `libraryVariants` or `applicationVariants`.
final String demoQaOutput = await inDirectory(hostAppDir, () async {
return eval(
gradlewExecutable,
<String>[
'app:assembleDemoQa',
'-Pandroid.newDsl=true',
'-Pflutter.hostAppProjectName=app',
],
environment: <String, String>{'JAVA_HOME': javaHome},
);
});

if (!demoQaOutput.contains(
"The Gradle property 'flutter.hostAppProjectName' has no effect.",
)) {
return TaskResult.failure(
'Expected a warning that flutter.hostAppProjectName has no effect',
);
}

final String demoQaApk = path.join(
hostAppDir.path,
'app',
'build',
'outputs',
'apk',
'demo',
'qa',
'app-demo-qa.apk',
);

if (!exists(File(demoQaApk))) {
return TaskResult.failure('Failed to build app-demo-qa.apk');
}

section('Verify AOT ELF in app-demo-qa.apk');

final Iterable<String> demoQaFiles = await getFilesInApk(demoQaApk);
checkCollectionContains<String>(<String>[
...flutterAssets,
'lib/arm64-v8a/libapp.so',
'lib/armeabi-v7a/libapp.so',
], demoQaFiles);
checkCollectionDoesNotContain<String>(debugAssets, demoQaFiles);

return TaskResult.success(null);
} on TaskResult catch (taskResult) {
return taskResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ android {
initWith release
matchingFallbacks += 'release'
}
// Debuggable, but consumes the module's release variant, so it gets release Flutter
// artifacts.
qa {
initWith debug
matchingFallbacks += 'release'
}
}
// Test flavors.
flavorDimensions += "version"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
flutter.hostAppProjectName=SampleApp
Comment thread
reidbaker marked this conversation as resolved.
Resolved
android.newDsl=false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewers, Ignore this file I dont think it is worth your time.

Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,10 @@ projects. That opt-out dies with AGP 10.
5. **`buildModeFor` semantics.** Every variant-scope call uses the
`(name, debuggable)` overload with the public `Component.debuggable`.
Name-based inference is confined to the one DSL-scope case with no public
signal (the library-plugin build-type copy in `PluginHandler`). This
preserves add-to-app custom-debuggable matching (a host `staging`
debuggable build type maps to debug engine artifacts).
signal (the library-plugin build-type copy in `PluginHandler`). In an
add-to-app module the call reads the module's own variant, so the build mode
follows the module variant that the host's `matchingFallbacks` select (see
"Features that must break" item 6).
6. **P3 pre-spike / PR 4 (afterEvaluate DSL mutation under newDsl).** The planned scratch-app
spike (AGP 9.1 + `newDsl=true` + custom build type, verifying that build-type
creation from `pluginProject.afterEvaluate` still works) could not run in the
Expand Down Expand Up @@ -237,12 +238,23 @@ else serializes through `FlutterPlugin.kt` / `FlutterPluginUtils.kt`.
but C++ debugging will be broken for those custom build types.
5. **Asset merge**: flutter assets become a merged source dir instead of a
post-merge overwrite; collisions resolve by AGP source-set priority.
6. **Add-to-app**: the explicit `:app:merge<V>Assets.dependsOn` edge and
host-project lookup are removed; `flutter.hostAppProjectName` becomes a
no-op with a deprecation warning naming a removal milestone. Build scripts that
reference Flutter's `copyFlutterAssets<V>` tasks by name (e.g. `tasks.getByPath(...)`)
will crash with a `Task with path ... not found` error because the tasks are now
registered lazily.
6. **Add-to-app**: the module registers its Flutter tasks in its own `onVariants` and
adds the staged assets and native libraries as generated source directories of each
library variant. The host consumes them like any Android library's, so the
host-project lookup, the `libraryVariants` × host `applicationVariants` loop and the
`:app:merge<V>Assets.dependsOn` edge are removed.
- `flutter.hostAppProjectName` has no effect; setting it logs a warning that names no
removal milestone.
- Every module variant is configured whatever the command line names, because the
host's `matchingFallbacks`, not the task name, decide which module variant a host
task consumes. Registration is lazy, so only that variant runs. Cost: a host build
of only `assemble<Variant>AndroidTest` runs the module's `flutter assemble`.
- The build mode comes from the consumed module variant, not the host build type. A
debuggable host build type that falls back to the module's `release` gets release
artifacts. Built as the only task, the deleted code ran the module's debug Flutter
build for it, and the APK had no `flutter_assets` and no `libapp.so`.
- Module assets are a generated source directory (item 5), and `copyFlutterAssets<V>`
is a `CopyFlutterAssetsTask` (item 7).
7. **Task realization/type**: flutter tasks become lazy `TaskProvider`s, and
`copyFlutterAssets<V>` changes type from `org.gradle.api.tasks.Copy` to a
custom task class — `tasks.named(..., Copy::class)` casts fail.
Expand Down
35 changes: 17 additions & 18 deletions docs/platforms/android/website-page-draft.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewers, Ignore this file I dont think it is worth your time. It is more valuable than the migrateing md file but still probalby not worth it.

Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,27 @@ aliases:

### Add-to-app (Flutter module in a host app)

- Flutter no longer looks up or configures the host `:app` project from the
module. The dependency between your host's asset merging and Flutter's asset
copy is expressed through the Variant API instead of an explicit
`merge<Variant>Assets.dependsOn(...)` edge. Build scripts that reference
Flutter's `copyFlutterAssets<Variant>` tasks by name or type will break.
For example, `tasks.getByPath(":flutter:copyFlutterAssetsDebug")` will crash
your build with a `Task with path ... not found` error because the
tasks are now registered lazily and are no longer of type
`org.gradle.api.tasks.Copy`.
- `flutter.hostAppProjectName` in `gradle.properties` is now a no-op. Flutter
prints a deprecation warning naming the removal milestone. It was only used
for the host-project lookup, which no longer exists.
- Flutter maps host build types to Flutter build modes using the public
"debuggable" flag: `profile` stays `profile`, debuggable build types map to
`debug`, everything else maps to `release`. If your host has no `profile`
build type, add `matchingFallbacks`:
- The Flutter module adds its assets and native libraries to its own variants
through the Variant API. Your host app consumes them like the assets of any
Android library. Flutter does not look up or configure the host `:app`
project, and adds no `merge<Variant>Assets.dependsOn(...)` edge to it.
- `flutter.hostAppProjectName` in `gradle.properties` has no effect. If it is
set, Flutter prints a warning that says so. You can remove it.
- The Flutter module's `copyFlutterAssets<Variant>` tasks are of type
`CopyFlutterAssetsTask`, not `org.gradle.api.tasks.Copy`. Build scripts that
look them up with the `Copy` type fail.
- The Flutter build mode comes from the module variant your host build
consumes: the module's `debug` variant builds debug Flutter artifacts,
`profile` builds profile, and `release` builds release. Host `debug`,
`profile` and `release` build types consume the module variant of the same
name. For a custom host build type, AGP picks the module variant through the
build type's `matchingFallbacks`, so list the module build type you want
first:

```kotlin
create("staging") {
initWith(getByName("debug"))
isDebuggable = true // staging gets debug Flutter artifacts

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is isDebuggable deleted here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was deleted on purpose, in 8c9a54d.

The text it illustrated said Flutter maps host build types to build modes using the debuggable flag. That mapping (buildModeFor(com.android.builder.model.BuildType), which read isDebuggable) is deleted in this PR. The mode comes from the module variant that matchingFallbacks selects, so the flag doesn't affect the Flutter artifacts.

It was also redundant in the snippet: initWith(getByName("debug")) already makes staging debuggable (BuildType.initWith: "Copies all properties from the given build type.").

The PR body shows the effect: a debuggable qa that falls back to release gets release Flutter artifacts (libapp.so, compileFlutterBuildRelease), and the devicelab qa section checks that.

matchingFallbacks += listOf("debug", "release")
matchingFallbacks += listOf("debug", "release") // staging gets debug Flutter artifacts
}
```

Expand Down
Loading
Loading