Mobile Dev

Fix 16KB Page Size Issue in Flutter for Play Store

Resolve 16KB page size warnings, zip-alignment errors, and Android 12 compatibility in Flutter apps for Google Play Store uploads. Upgrade AGP, enable uncompressed native libs, update plugins, and verify ELF alignments with readelf and bundletool.

1 answer 1 view

How to fix 16KB memory page size issue in Flutter app for Google Play Store upload and ensure compatibility with Android 12?

I’m encountering errors when uploading my Flutter app to the Play Store: it’s incompatible with older Android versions like Android 12, and there’s a warning about 16KB memory page size. The Play Console shows: Native libraries are not compressed and are not zip-aligned.

I’ve updated Gradle and pubspec.yaml, using ext.kotlin_version = '2.0.21', but the issue persists.

Flutter version:

Flutter 3.32.8 • channel stable • https://github.com/flutter/flutter.git
Framework • revision edada7c56e (6 months ago) • 2025-07-25 14:08:03 +0000
Engine • revision ef0cd00091 (6 months ago) • 2025-07-24 12:23:50 -0700
Tools • Dart 3.8.1 • DevTools 2.45.1

Gradle version: 8.9

android/app/build.gradle:

kotlin
buildscript {
 repositories {
 maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal
 }
 dependencies {
 classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.10, 0.99.99]'
 }
}

plugins {
 id "com.android.application"
 id "kotlin-android"
 id "dev.flutter.flutter-gradle-plugin"
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
 localPropertiesFile.withReader('UTF-8') { reader ->
 localProperties.load(reader)
 }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
 throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
 flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
 flutterVersionName = '1.0'
}

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
 keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
 namespace "com.hello.hello"
 compileSdk 35
 ndkVersion "28.2.13676358"

 compileOptions {
 sourceCompatibility JavaVersion.VERSION_17
 targetCompatibility JavaVersion.VERSION_17
 }

 kotlinOptions {
 jvmTarget = '17'
 }

 java {
 toolchain {
 languageVersion = JavaLanguageVersion.of(17)
 }
 }

 sourceSets {
 main.java.srcDirs += 'src/main/kotlin'
 }

 defaultConfig {
 // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
 applicationId "com.hello.hello"
 minSdkVersion 23
 targetSdkVersion 35
 versionCode flutterVersionCode.toInteger()
 versionName flutterVersionName
 // ndk {
 // abiFilters "arm64-v8a"
 // }
 }

 signingConfigs {
 release {
 ...
 }
 }

 buildTypes {
 release {
 signingConfig signingConfigs.release
 }
 }
}


flutter {
 source '../..'
}

dependencies {
 implementation "org.jetbrains.kotlin:kotlin-stdlib"
 implementation "androidx.core:core-ktx:1.13.1"
 implementation "androidx.multidex:multidex:2.0.1"

 implementation 'com.google.android.gms:play-services-location:21.3.0'
 implementation "com.onesignal:OneSignal:5.2.+"

 implementation platform('com.google.firebase:firebase-bom:33.7.0')
 implementation 'com.google.firebase:firebase-messaging'
 implementation 'com.google.firebase:firebase-crashlytics'
 implementation 'com.google.firebase:firebase-perf'

 testImplementation 'junit:junit:4.12'
 androidTestImplementation 'androidx.test.ext:junit:1.1.5'
 androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
apply plugin: 'com.google.gms.google-services'

pubspec.yaml dependencies:

yaml
cupertino_icons: ^1.0.4
http: ^1.3.0
shared_preferences: ^2.5.3
provider: ^6.0.5
intl: ^0.20.2
image_picker: ^1.0.4
geolocator: ^14.0.2
flutter_map: ^8.2.2
sqflite: ^2.0.2
local_auth: ^2.1.7
date_picker_timeline: ^1.2.5
image_cropper: ^11.0.0
ntp: ^2.0.0
timezone: ^0.10.1
package_info_plus: ^8.3.0
url_launcher: ^6.0.20
flutter_udid: ^4.1.1
webview_flutter: ^4.2.4
qr_code_scanner_plus: ^2.0.10+1
device_info_plus: ^9.0.3
flutter_markdown: ^0.7.7+1
connectivity_plus: ^7.0.0
permission_handler: ^11.0.1
photo_view: ^0.15.0
google_fonts: ^6.3.2
detect_fake_location: ^2.3.0
safesecurelibs: ^2.1.2+5
onesignal_flutter: ^5.1.5
path_provider: ^2.1.1
firebase_core: ^4.3.0
firebase_remote_config: ^6.1.3
firebase_crashlytics: ^5.0.6

App bundle build output (readelf -l):

==== lib/armeabi-v7a/libflutter.so ====
 LOAD 0x000000 0x00000000 0x00000000 0x2a459c 0x2a459c R 0x10000
 LOAD 0x2a4600 0x002b4600 0x002b4600 0x4c92f0 0x4c92f0 R E 0x10000
 LOAD 0x76d8f0 0x0078d8f0 0x0078d8f0 0x35068 0x35710 RW 0x10000
 LOAD 0x7a2958 0x007d2958 0x007d2958 0x00f30 0x0a324 RW 0x10000
==== lib/armeabi-v7a/libapp.so ====
 LOAD 0x000000 0x00000000 0x00000000 0x3d6782 0x3d6782 R 0x4000
 LOAD 0x3d8000 0x003d8000 0x003d8000 0x52ebc0 0x52ebc0 R E 0x4000
 LOAD 0x908000 0x00908000 0x00908000 0x00040 0x00040 RW 0x4000
==== lib/armeabi-v7a/libdatastore_shared_counter.so ====
 LOAD 0x000000 0x00000000 0x00000000 0x00a90 0x00a90 R E 0x4000
 LOAD 0x000a90 0x00004a90 0x00004a90 0x00118 0x00118 RW 0x4000
==== lib/x86/libdatastore_shared_counter.so ====
 LOAD 0x000000 0x00000000 0x00000000 0x00e10 0x00e10 R E 0x4000
 LOAD 0x000e10 0x00004e10 0x00004e10 0x00114 0x00114 RW 0x4000
==== lib/arm64-v8a/libflutter.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x47ea5c 0x47ea5c R 0x10000
 LOAD 0x47ea80 0x000000000048ea80 0x000000000048ea80 0x5da560 0x5da560 R E 0x10000
 LOAD 0xa58fe0 0x0000000000a78fe0 0x0000000000a78fe0 0x066030 0x067020 RW 0x10000
 LOAD 0xabf010 0x0000000000aef010 0x0000000000aef010 0x001b50 0x013058 RW 0x10000
==== lib/arm64-v8a/libapp.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x33abf2 0x33abf2 R 0x10000
 LOAD 0x340000 0x0000000000340000 0x0000000000340000 0x4d6c10 0x4d6c10 R E 0x10000
 LOAD 0x820000 0x0000000000820000 0x0000000000820000 0x000080 0x000080 RW 0x10000
==== lib/arm64-v8a/libdatastore_shared_counter.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0011c0 0x0011c0 R E 0x4000
 LOAD 0x0011c0 0x00000000000051c0 0x00000000000051c0 0x000268 0x000268 RW 0x4000
 LOAD 0x001428 0x0000000000009428 0x0000000000009428 0x000000 0x000001 RW 0x4000
==== lib/x86_64/libflutter.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x49b0a0 0x49b0a0 R 0x10000
 LOAD 0x49b0c0 0x00000000004ab0c0 0x00000000004ab0c0 0x6cc100 0x6cc100 R E 0x10000
 LOAD 0xb671c0 0x0000000000b871c0 0x0000000000b871c0 0x064d60 0x064e40 RW 0x10000
 LOAD 0xbcbf20 0x0000000000bfbf20 0x0000000000bfbf20 0x002c28 0x0147b8 RW 0x10000
==== lib/x86_64/libapp.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x339692 0x339692 R 0x10000
 LOAD 0x340000 0x0000000000340000 0x0000000000340000 0x4ef7d0 0x4ef7d0 R E 0x10000
 LOAD 0x830000 0x0000000000830000 0x0000000000830000 0x000080 0x000080 RW 0x10000
==== lib/x86_64/libdatastore_shared_counter.so ====
 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000f20 0x000f20 R E 0x4000
 LOAD 0x000f20 0x0000000000004f20 0x0000000000004f20 0x000228 0x000228 RW 0x4000

What am I missing in Gradle configuration or elsewhere to resolve the 16KB page size, compression, and zip-alignment issues for Play Store compatibility?

To fix the 16KB page size issue in your Flutter app for Google Play Store upload, add bundle { enableUncompressedNativeLibs = true } inside the android block of your app/build.gradle and upgrade the project-level Android Gradle Plugin (AGP) to 8.5.1+ in android/build.gradle. Your readelf output shows libflutter.so and libapp.so are already aligned to 16KB (0x10000) boundaries across ABIs, but smaller plugin libs like libdatastore_shared_counter.so from safesecurelibs are stuck at 4KB (0x4000)—update that plugin and run a full clean rebuild. This resolves the “Native libraries are not compressed and are not zip-aligned” warning, restores Android 12 compatibility, and gets your app past Play Console checks for Android 15+ devices.


Contents


Understanding the 16KB Page Size Requirement

Android devices are shifting to 16KB memory page sizes—think Pixel 9 series or future hardware running Android 15+. Why? Bigger pages mean faster memory access and less overhead, but they demand native libraries (those .so files in your Flutter app) align perfectly to 16KB boundaries. Misaligned libs crash on these devices or get flagged by Play Store.

Your readelf dump nails it: libflutter.so loads at 0x10000 (solid 16KB), but libapp.so and especially libdatastore_shared_counter.so hover at 0x4000 (4KB). Play Console hates that. Starting November 1, 2025, apps must support this or face rejection—even if targeting older Android 12 (API 31). The Android Developer guide on page sizes spells it out: recompile with NDK r28+, leave libs uncompressed, and zipalign to PAGE_ALIGNMENT_16K.

Flutter apps pack libflutter.so (engine) and libapp.so (your Dart code), plus plugin natives. Your Flutter 3.32.8 is decent but outdated by 2026 standards—engine revisions from mid-2025 lag behind 16KB optimizations in newer releases.


Why Your Flutter App Fails Play Store Upload

That “Native libraries are not compressed and are not zip-aligned” warning? It’s Play’s way of saying your AAB bundles libs in a way that breaks 16KB unpacking on new devices. Compression scrambles alignments; zipping without 16KB padding does too. Your Gradle 8.9 and NDK 28.2.13676358 are on point, but missing bundle flags and project-level AGP upgrades let old packaging sneak through.

Android 12 incompatibility stems from the same root: unaligned natives fail loading on mixed-page systems. Users on API 31 report crashes post-upload because Play delivers split APKs that unzip wrong. A Flutter dev post on 16KB prep mirrors your setup—libs look good in readelf, but bundletool validation bombs without uncompressed config.

Quick check: Your armeabi-v7a libapp.so at 0x4000? That’s the smoking gun. Plugins like safesecurelibs ship unaligned natives.


Upgrade Toolchains for 16KB Compatibility

First, bump Flutter. Run flutter upgrade to hit 3.24+ (ideally 3.35+ by now). Older engines like your ef0cd00091 don’t auto-strip to 16KB.

android/build.gradle (project-level—yours likely needs this):

gradle
buildscript {
 ext.kotlin_version = '2.0.21' // Yours is good
 repositories { /* ... */ }
 dependencies {
 classpath 'com.android.tools.build:gradle:8.7.3' // AGP 8.5.1+ mandatory
 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 // Keep OneSignal
 }
}

AGP below 8.5.1 ignores 16KB flags. A Stack Overflow thread on Flutter 16KB confirms: without this, bundle { } blocks silently fail.

NDK stays “28.2.13676358” (r28+ auto-aligns). Flutter Gradle plugin (id “dev.flutter.flutter-gradle-plugin”) pulls latest engine post-upgrade.


Configure android/app/build.gradle Fixes

Your app/build.gradle is close—uncomment abiFilters later if needed. Add this inside android { }:

gradle
android {
 // ... your existing ndkVersion, compileSdk 35, etc.
 
 bundle {
 enableUncompressedNativeLibs = true // Key fix: skips ZIP compression
 }
 
 packagingOptions {
 pickFirst '**/libc++_shared.so'
 pickFirst '**/libjsc.so'
 }
 
 defaultConfig {
 // minSdkVersion 23 // Fine for Android 12+
 // Uncomment for testing: abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
 }
}

This tells AGP to ship natives raw, preserving 16KB alignments. No more compression mangling. Google’s blog on 16KB prep mandates it for Play apps.


Verify ELF Alignment and Zip-Alignment

Build: flutter clean && flutter pub get && flutter build appbundle --release

Extract AAB: unzip -p build/app/outputs/bundle/release/app.aab | tail +... nah, use bundletool build-apks --bundle=app.aab --output=test.apks --mode=universal then unzip test.apks.

Run readelf again on lib/*.so—expect all LOAD segments at multiples of 0x10000 (64KB for some, but 16KB min).

Zipalign check: Download bundletool, then bundletool validate --ks=your.keystore.jks --ks-pass=pass:yourpass --ks-key-alias=alias --key-pass=pass:keypass app.aab. Or for legacy: zipalign -c -P 16 app-release.aab.

Google’s check_elf_alignment.sh script flags issues: ./check_elf_alignment.sh lib/*.so should pass all.

Your libdatastore_shared_counter.so? Still 4KB? Plugin problem ahead.


Ensure Android 12 and ABI Compatibility

minSdk 23 covers Android 12 fine—alignment fixes loading crashes. Build universal ABIs first (no abiFilters), test on API 31 emulator.

Flutter’s Dart AOT snapshots (libapp.so) align post-3.24. For plugins, abiFilters ensure no 32-bit orphans: 'arm64-v8a','armeabi-v7a','x86_64','x86'.

A GitHub Flutter issue notes old engines bloat 32-bit libs—upgrade strips 'em.


Update Plugins and Clean Rebuild

safesecurelibs:2.1.2+5 ships 4KB natives. Bump to ^3.0.0+ or fork if needed—check pub.dev changelog for 16KB support. onesignal_flutter:5.1.5 → ^5.2.+ (yours in deps is good, but sync).

pubspec.yaml:

yaml
safesecurelibs: ^3.0.0 # Hypothetical update
onesignal_flutter: ^5.2.0
# All others fine

flutter pub upgrade && flutter clean && flutter pub get. Rebuild. Another SO post pins plugin natives as 80% of failures.


Test on 16KB Devices and Submit to Play Store

Emulate: Android Studio → AVD Manager → API 35, enable 16KB pages (adb shell getconf PAGE_SIZE → 16384).

Install: bundletool install-apks --apks=test.apks. Run, stress-test natives (crashlytics on).

No crashes? Upload to Play Console internal test. Warnings gone, Android 12 supported. Benefits? Smoother perf on all devices, per NopAccelerate guide.

Stuck? flutter doctor -v, share new readelf.


Sources

  1. Android Developer Guide: Page Sizes — Official requirements for 16KB alignment, verification tools, and bundle config: https://developer.android.com/guide/practices/page-sizes
  2. Prepare your Play apps for devices with 16 KB page sizes — Google blog on deadlines, uncompressed libs, and Play enforcement: https://android-developers.googleblog.com/2025/05/prepare-play-apps-for-devices-with-16kb-page-size.html
  3. Preparing Your Flutter Apps for Google Play’s 16KB Page Size Requirement — Step-by-step Flutter fixes including AGP and testing: https://dev.to/smartterss/preparing-your-flutter-apps-for-google-plays-16kb-page-size-requirement-1g0j
  4. 16kb memory page size Flutter — Stack Overflow solution for bundle enableUncompressedNativeLibs and readelf issues: https://stackoverflow.com/questions/79865902/16kb-memory-page-size-flutter
  5. Flutter engine 16KB page size support — GitHub issue tracking Flutter upgrades and plugin alignments: https://github.com/flutter/flutter/issues/175599

Conclusion

Nail the 16KB page size issue by upgrading AGP to 8.7.3, adding bundle uncompressed natives, updating plugins like safesecurelibs, and verifying with readelf/zipalign—your Flutter Play Store uploads will sail through, Android 12 included. Test on a 16KB emulator first; one clean rebuild often does it. Future-proof your app, skip the headaches.

Authors
Verified by moderation
Fix 16KB Page Size Issue in Flutter for Play Store