ci(android): fix split build, produce universal APK in the same Gradle run
Build Android APK / Build Release APKs (push) Successful in 14m40s

The previous commit made `assembleRelease` depend on AGP's
`packageReleaseUniversalApk`. That task derives the universal APK from an
App Bundle, which pulls `buildReleasePreBundle` into the graph - and AGP
refuses to build a bundle while ABI splits are enabled
("Multiple shrunk-resources files found ... Please disable building
multiple APKs when building an Android app bundle", run 52).

Instead only flip `splits.abi.universalApk` back on when Flutter passes
`-Psplit-per-abi=true`: the Flutter Gradle plugin enables the splits and
copies every output - including the universal one, as app-release.apk -
to build/app/outputs/flutter-apk/. Plain builds (`flutter run`) keep the
plugin's abiFilters path, which AGP does not allow together with splits.

Workflow: one `flutter build apk --release --split-per-abi` call, copy the
four well-known output names (a missing one fails the step), job timeout
60 min (a green run takes ~17), drop the unneeded platform pre-install and
add a per-ref concurrency group - runs 50/51 ran in parallel on the single
ARM64 runner and both died at the same instant.

Verified locally with Flutter 3.47.4: split build yields all four APKs
(universal 62 MB, per-ABI 20-24 MB) in one Gradle run; plain release
build still produces app-release.apk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-17 23:30:13 +02:00
co-authored by Claude Opus 5
parent b7b6c4a2ab
commit a228392dc6
2 changed files with 35 additions and 71 deletions
+15 -12
View File
@@ -34,26 +34,29 @@ android {
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
splits {
abi {
enable true
reset()
include "arm64-v8a", "armeabi-v7a", "x86_64"
universalApk true
// `flutter build apk --split-per-abi` makes the Flutter Gradle plugin enable ABI
// splits for the requested target platforms but switch the universal APK off.
// Turn it back on so a single Gradle run yields the per-ABI APKs *and* the
// universal one (the plugin copies all of them to build/app/outputs/flutter-apk/,
// the universal one as app-release.apk). Only when splitting: for plain builds
// the plugin sets ndk.abiFilters instead, which AGP does not allow together
// with splits. Do not use AGP's `packageReleaseUniversalApk` task for this -
// it derives the universal APK from an App Bundle, and bundles cannot be
// built while ABI splits are enabled.
if (project.findProperty("split-per-abi")?.toString()?.toBoolean()) {
splits {
abi {
universalApk true
}
}
}
}
afterEvaluate {
tasks.named('assembleRelease').configure {
dependsOn 'packageReleaseUniversalApk'
}
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17