effidevFlutter · Cloudflare-Edge · Cloud-Kostenoptimierung

Wenn Google Play deine Flutter-App auch nach der Frist im Mai 2026 ablehnt: Praxisleitfaden zur 16-KB-Seitengröße

Wenn Google Play deine Flutter-App auch nach der Frist im Mai 2026 ablehnt: Praxisleitfaden zur 16-KB-Seitengröße

“Ich dachte, das hätte ich letztes Jahr schon erledigt – warum wird die App schon wieder abgelehnt?” Diese Frage taucht seit einigen Wochen immer wieder in Flutter-Entwickler-Communitys und Issue-Trackern auf. Die Anforderung von Google Play zur 16-KB-Speicherseitengröße trat ursprünglich am 1. November 2025 in Kraft, konnte aber über einen individuellen Antrag bis maximal 31. Mai 2026 aufgeschoben werden. Heute ist der 24. Juli 2026 – diese Fristverlängerung liegt also schon fast zwei Monate zurück. Trotzdem werden noch immer viele Apps beim Hochladen eines Updates abgelehnt. Der Grund ist fast immer derselbe: Der eigene App-Code wurde zwar angepasst, aber ein genutztes Drittanbieter-Plugin mit nativem Code ist noch nicht auf 16 KB ausgerichtet.

Dieser Beitrag ist keine bloße Ankündigungs-Zusammenfassung, sondern ein praxisorientierter Leitfaden für alle, die gerade konkret an diesem Problem hängen.

Kurz zusammengefasst

  • Google Play verlangt 16-KB-Seitenausrichtung für neue Apps/Updates, die Android 15 (API 35) oder höher als Target haben und nativen Code (.so) enthalten. Apps mit reinem Dart-Code sind nicht betroffen.
  • Die ursprüngliche Frist war der 1. November 2025, über einen individuellen Aufschub war eine Verlängerung bis maximal 31. Mai 2026 möglich. Ab diesem Zeitpunkt gilt die Anforderung ohne weiteren Aufschub sofort.
  • Die Flutter-Engine selbst (libflutter.so, libapp.so) unterstützt ab Flutter 3.32.8 16 KB. Das eigentliche Problem sind meist die .so-Dateien, die Drittanbieter-Plugins mitbringen.
  • Mit zipalign, llvm-objdump und dem App Bundle Explorer der Play Console lässt sich das im Voraus selbst überprüfen.
  • Ohne einen Ausrichtungs-Check in der CI-Pipeline kommt dieses Problem garantiert wieder.

Warum es die 16-KB-Anforderung gibt und wen sie betrifft

Traditionell verwaltet Android den Speicher in 4-KB-Einheiten (Pages). Ab Android 15 unterstützt AOSP nun auch 16-KB-Seitengrößen, und neu erscheinende High-End-Geräte (mit viel RAM) gehen zunehmend dazu über, standardmäßig 16-KB-Seiten zu verwenden. In der offiziellen Dokumentation (developer.android.com/guide/practices/page-sizes) nennt Google folgende, aus eigenen Tests ermittelte Verbesserungen (Google weist selbst darauf hin, dass es sich um “erste Testergebnisse” handelt, die auf realen Geräten abweichen können):

Aufgrund dieser Zahlen hat Google festgelegt, dass ab dem 1. November 2025 neue Apps und Updates bestehender Apps, die Android 15 (API 35) oder höher als Target haben, auf 64-Bit-Geräten die 16-KB-Seitengröße unterstützen müssen. Wie sich in zahlreichen Entwickler-Community-Threads bestätigt (etwa “Clarification on 16 KB page size extension” in der Google-Play-Entwickler-Community), ließ sich das über einen individuellen Aufschubantrag in der Play Console vorübergehend bis zum 31. Mai 2026 verschieben. Zum Zeitpunkt dieses Artikels (Juli 2026) ist auch dieser Aufschub bereits abgelaufen, sodass nicht angepasste Apps schon beim Hochladen des Updates blockiert werden.

Wichtig dabei: Reine Dart-/Flutter-Apps ohne nativen Code müssen überhaupt nichts unternehmen. Auch der offizielle Google-Blog stellt klar, dass Apps ohne nativen Code keine Änderungen benötigen und bereits kompatibel sind. Das eigentliche Problem betrifft die überwiegende Mehrheit der Flutter-Apps in der Praxis, die für Kamera, Animationen, Datenbanken, Karten oder Zahlungs-SDKs native Plugins mit .so-Dateien einsetzen.

So prüfst du, ob deine App betroffen ist: Diagnose in drei Schritten

Schritt 1 — Zuerst die Liste der nativen Plugins erstellen

Gehe zunächst die Abhängigkeiten in pubspec.yaml durch und markiere alle Pakete, die potenziell nativen Code enthalten. Zu den typischen Verdächtigen zählen Kamera-Plugins, Datenbanken (sqlite, realm, isar mit nativem Backend), Karten (google_maps_flutter), Animationen (rive, lottie mit nativem Renderer), Bildverarbeitung (flutter_image_compress), Zahlungs-/Sicherheits-SDKs, Crash-Reporter (sentry_flutter, firebase_crashlytics), WebRTC sowie ML-Inferenz (tflite, onnxruntime).

Schritt 2 — Die .so-Dateien im Build-Artefakt direkt untersuchen

Bloßer Verdacht reicht nicht aus – schau dir das tatsächliche Build-Ergebnis an.

# zuerst einen Release-Build erstellen
flutter build appbundle --release

# im Bundle enthaltene .so-Dateien auflisten
unzip -l build/app/outputs/bundle/release/app-release.aab | grep "\.so"

Ob eine einzelne .so-Datei auf 16 KB ausgerichtet ist, lässt sich direkt mit llvm-objdump prüfen (Beispielpfad für macOS):

$ANDROID_HOME/ndk/<NDK_VERSION>/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump \
  -p path/to/librive_text.so | grep LOAD

Steht in der Ausgabe align 2**14 (16384 Byte), ist alles in Ordnung; erscheint 2**13 (8192) oder weniger, liegt eine 4-KB-Ausrichtung vor und damit ein Problem. Um das gesamte AAB auf einen Schlag zu prüfen, eignet sich außerdem bundletool.

bundletool dump config --bundle=app-release.aab | grep alignment
# PAGE_ALIGNMENT_16K ist in Ordnung, PAGE_ALIGNMENT_4K bedeutet nicht angepasst

Auf APK-Ebene lässt sich der Prüfmodus von zipalign verwenden.

$ANDROID_HOME/build-tools/35.0.0/zipalign -v -c -P 16 4 app-release.apk

Wer Android Studio verwendet, kommt über File > Profile or Debug APK (bzw. Build > Analyze APK) am schnellsten zum Ziel: Öffne die Datei und schau dir im Ordner lib/arm64-v8a die Spalte Alignment an. Die Datei mit dem Warnsymbol ist der Übeltäter.

Schritt 3 — Vorabprüfung vor dem Upload in die Play Console

Der App Bundle Explorer der Play Console zeigt nach dem Upload eines AAB automatisch alle Bibliotheken an, die nicht auf 16 KB ausgerichtet sind. Bei tatsächlichen Ablehnungen tauchen typischerweise folgende Meldungen auf:

Da der Dateiname exakt in der Meldung steht, musst du nur noch zurückverfolgen, aus welchem Plugin diese .so-Datei stammt.

Kompatibilitätsmatrix für Flutter-, NDK- und AGP-Versionen

Komponente Mindestanforderung Empfohlen Anmerkung
Flutter SDK 3.32.8+ aktuellste stable-Version (3.35 oder höher) Ab 3.32.8 unterstützt die Engine selbst 16 KB. Aktuelle Version mit flutter doctor -v prüfen
Android NDK r27+ r28-Reihe Ab r28 wird standardmäßig mit 16-KB-Ausrichtung kompiliert. Bei r27 müssen die Linker-Flags manuell gesetzt werden
AGP (Android Gradle Plugin) 8.5.1+ aktuellste 8.7.x oder höher 8.3–8.5 erzeugen zwar eine 16-KB-Ausrichtung, aber bundletool führt kein automatisches Zipalign der APK durch
Gradle 8.9+ zur jeweiligen AGP-Version passende neueste Fassung Bezogen auf die kompatible Kombination mit AGP 8.5.1
Android SDK Build-Tools 35.0.0+ aktuellste Version Die Option zipalign -P 16 wird erst ab dieser Version unterstützt
compileSdk / targetSdk 35 35 oder höher API-Level von Android 15

Es gibt eine Falle: Stand Juli 2026 setzt das flutter_tools-Gradle-Plugin von Flutter standardmäßig die NDK-Version 27.0.12077973 (bestätigt in Issue #175022 von flutter/flutter). r27 erfüllt zwar formal die Mindestanforderung, kompiliert aber standardmäßig nicht mit 16-KB-Ausrichtung. Um auf der sicheren Seite zu sein, musst du entweder die Linker-Flags selbst ergänzen oder auf die r28-Reihe des NDK wechseln. In android/app/build.gradle (bzw. .kts) legst du das so fest:

android {
    ndkVersion "28.2.13676358" // auf der Download-Seite die aktuellste r28.x prüfen und hier eintragen

    defaultConfig {
        externalNativeBuild {
            cmake {
                // falls r27 beibehalten werden muss, dieses Flag ergänzen
                arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
            }
        }
    }
}

Bei Legacy-Projekten mit AGP 8.0 oder niedriger ist außerdem folgende Zeile in gradle.properties nötig.

android.bundle.enableUncompressedNativeLibs=false

Ein weiterer, in der Praxis häufig gemeldeter Bug: Bei bestimmten Kombinationen aus Flutter 3.32.8/3.35.1 und einer bestimmten AGP-Version löst das Anheben von minSdkVersion auf 23 oder höher selbst in frisch angelegten Projekten eine 16-KB-Warnung im App Bundle Explorer aus (flutter/flutter Issue #173949). Senkt man minSdkVersion auf 21 oder niedriger, verschwindet die Warnung zwar – das ist aber keine echte Lösung, sondern nur ein Ausweichen. Empfehlenswerter ist es, Flutter und AGP auf die jeweils neueste stabile Version zu bringen.

Wenn ein Drittanbieter-Plugin noch nicht angepasst ist: Praxisbeispiele und Strategien

Am ärgerlichsten ist die Situation, wenn der eigene Code bereits vollständig angepasst ist, aber der Anbieter eines genutzten Plugins die .so-Datei noch nicht neu gebaut hat. Schauen wir uns zwei real dokumentierte Fälle an.

Fall 1 — Rive-Animationen. Im bisherigen rive-Paket (Reihe 0.13.x) ist librive_text.so mit 4-KB-Ausrichtung gebaut, weshalb die Play Console das Bundle direkt ablehnt. Im Repository rive-app/rive-flutter taucht diese Anfrage in den Issues #458, #488, #524, #539, #547 und #553 seit fast über einem Jahr immer wieder auf. Die eigentliche Lösung besteht nicht darin, am veralteten rive-Paket festzuhalten, sondern auf den Nachfolger rive_native zu migrieren. rive_native vermerkt ab Version 0.0.3 im Changelog unter Verweis auf Issue #479 explizit “Android: support 16 KB page sizes”.

Fall 2 — SQLite. Bei sqlite3_flutter_libs wurde das Problem mit Version 0.5.25 gelöst, im Changelog steht “Support 16KiB page sizes on Android 15”. Allerdings ist das Paket selbst inzwischen (Stand 0.6.0+eol) deprecated, und der Changelog weist darauf hin, dass sqlite3_flutter_libs ab sqlite3 3.x nicht mehr benötigt wird. Gerade bei älteren Projekten ist also oft schon das schlichte Aktualisieren der Pakete die Lösung.

Aus diesen beiden Fällen lässt sich folgende praktische Vorgehensreihenfolge ableiten.

  1. Zuerst ein Upgrade auf die neueste Version versuchen. Die meisten populären Pakete haben bereits eine angepasste Version veröffentlicht oder arbeiten daran. Durchsuche zuerst den Changelog nach den Schlüsselwörtern “16KB”, “page size” oder “alignment”.

  2. Mit dependency_overrides eine bestimmte transitive Abhängigkeit erzwingen. Das ist hilfreich, wenn das übergeordnete Paket selbst noch nicht aktualisiert wurde, das darin verwendete native Binding-Paket aber bereits in einer neuen Version vorliegt.

    dependency_overrides:
      rive_native: ^0.0.5
  3. Gradle exclude kombiniert mit einer direkt angegebenen, aktuellen AAR. Hat der Anbieter die neue .so-Datei als eigenes Maven-Artefakt veröffentlicht, kannst du die vom Plugin mitgebrachte alte AAR ausschließen und die neue Version direkt als Abhängigkeit hinzufügen.

    implementation("com.example:some-native-sdk:2.3.0") {
        exclude group: "com.example", module: "some-native-sdk-legacy"
    }
  4. Die .so-Datei direkt über ein jniLibs-Source-Set ersetzen. Wenn du eine von der Community neu kompilierte, 16-KB-ausgerichtete Binärdatei bekommen oder sie selbst mit dem NDK neu gebaut hast, fügst du ein Source-Set hinzu, das Vorrang vor der Vendor-AAR erhält.

    android {
        sourceSets {
            main {
                jniLibs.srcDirs += ["src/main/jniLibs16k"]
            }
        }
        packagingOptions {
            pickFirst "lib/arm64-v8a/librive_text.so"
        }
    }
  5. Wenn nichts davon hilft: forken. Ist das Plugin quelloffen, kannst du das Repository forken, lediglich die NDK-Version auf r28 anheben, neu bauen und den Fork anschließend in pubspec.yaml über einen Git-Pfad referenzieren – eine realistische Übergangslösung.

    dependencies:
      rive:
        git:
          url: https://github.com/<your-org>/rive-flutter.git
          ref: fix/16kb-alignment
  6. Als letztes Mittel eine Alternativbibliothek prüfen. Wenn beim Anbieter kein Zeitplan für eine Anpassung erkennbar ist, kann auch der Wechsel zu einem funktional ähnlichen Paket eine Option sein (etwa der Umstieg von einer veralteten Animationsbibliothek auf Lottie).

Wichtig ist klarzustellen: Der geräteseitige “16-KB-Kompatibilitätsmodus” (adb shell setprop bionic.linker.16kb.app_compat.enabled true) dient lediglich der bequemeren Entwicklungs- und Testphase — er ist kein Mechanismus, mit dem man die Prüfung in der Play Console besteht. Dieser Modus ist eine Einstellung auf dem Gerät des Nutzers, keine Eigenschaft des von dir ausgelieferten Builds.

Automatische Ausrichtungsprüfung in die CI-Pipeline einbauen

Damit ist es nicht ein für alle Mal erledigt. Wird die Plugin-Version wieder heruntergesetzt oder fügt ein neues Teammitglied ein nicht ausgerichtetes SDK hinzu, tritt das Problem erneut auf. Der Schlüssel, um das dauerhaft zu verhindern, ist, bei jedem Release-Build automatisch in der CI zu prüfen, ob die Ausrichtung stimmt, und den Build fehlschlagen zu lassen, bevor er in die Play Console hochgeladen wird. Hier ein Beispiel mit GitHub Actions.

name: android-release-check

on:
  push:
    branches: [main]

jobs:
  check-16kb-alignment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: subosito/flutter-action@v2
        with:
          channel: "stable"

      - name: Build App Bundle
        run: flutter build appbundle --release

      - name: Download bundletool
        run: |
          BUNDLETOOL_URL=$(curl -s https://api.github.com/repos/google/bundletool/releases/latest \
            | grep "browser_download_url.*jar" | cut -d '"' -f 4)
          curl -sL -o bundletool.jar "$BUNDLETOOL_URL"

      - name: Extract universal APK
        run: |
          java -jar bundletool.jar build-apks \
            --bundle=build/app/outputs/bundle/release/app-release.aab \
            --output=out.apks --mode=universal
          unzip -o out.apks -d out_apks

      - name: Verify 16KB page alignment
        run: |
          ZIPALIGN=$ANDROID_HOME/build-tools/35.0.0/zipalign
          $ZIPALIGN -v -c -P 16 4 out_apks/universal.apk || \
            (echo "::error::16-KB-Seitenausrichtung fehlgeschlagen — .so-Dateien prüfen" && exit 1)

Schlägt dieser Schritt fehl, zeigt die zipalign-Ausgabe direkt, welche .so-Datei das Problem verursacht – anhand des Dateinamens lässt sich sofort feststellen, welches Plugin dafür verantwortlich ist. Bei größeren Teams hilft es zusätzlich, mit Renovate oder Dependabot automatisch Update-PRs für native Pakete zu erhalten, die in der Vergangenheit bereits Probleme gemacht haben, etwa rive_native, sqlite3, google_maps_flutter oder sentry_flutter.

Abschluss-Checkliste

Wenn du gerade an diesem Problem hängst: In den meisten Fällen liegt die Ursache nicht im eigenen Code, sondern in veralteten nativen Drittanbieter-Abhängigkeiten. Gehst du die obige Reihenfolge Schritt für Schritt durch, lässt sich die Ursache in aller Regel innerhalb eines Tages eingrenzen.