What it means
Android devices are moving from 4 KB to 16 KB memory pages. The dynamic linker maps each LOAD segment of a shared library at a page boundary, so a library built with 4 KB alignment cannot be loaded as-is on a device that uses 16 KB pages. Apps without native code (pure Kotlin or Java) are not affected.
Google's page states that all apps targeting Android 15 (API level 35) and higher must support 16 KB memory page sizes on 64-bit devices on Google Play. Two things are checked: the ELF alignment of each 64-bit library (the align of every LOAD segment must be 2**14 or more), and, when android:extractNativeLibs is false, the offset of each uncompressed library inside the APK (what zipalign -c -P 16 verifies).
Deadline
From February 1, 2027, Google Play blocks the release of updates of apps that target API 35 or higher and do not support 16 KB page sizes. Until then the store check reports it as a warning; from that date, as a blocker.
How to fix it
1. Find the libraries that are not aligned
The store check lists every misaligned library with its smallest LOAD alignment. By hand, unzip the APK and inspect each 64-bit library:
llvm-objdump -p lib/arm64-v8a/libfoo.so | grep LOAD
# LOAD off 0x0000000 vaddr ... align 2**14 <- OK (16 KB)
# LOAD off 0x0000000 vaddr ... align 2**12 <- 4 KB, not OK2. Rebuild your own native code
NDK r28 and later compile 16 KB-aligned libraries by default: upgrading the NDK is the simplest fix. With NDK r27 or older, pass both linker flags:
target_link_options(foo PRIVATE
"-Wl,-z,max-page-size=16384"
"-Wl,-z,common-page-size=16384")3. Upgrade third-party SDKs that ship .so files
Most failures come from prebuilt libraries inside dependencies (image, video, database, crypto, game engine and analytics SDKs, older Flutter or React Native engines). The library path in the report usually names the SDK. Upgrade to a release built for 16 KB pages; rebuilding a prebuilt library yourself is rarely possible.
4. Package with AGP 8.5.1 or later
If the APK stores native libraries uncompressed (extractNativeLibs="false", the default with recent AGP), the Android Gradle Plugin 8.5.1+ aligns them on 16 KB boundaries. With an older plugin, the fallback is packaging { jniLibs { useLegacyPackaging = true } }, which compresses the libraries and makes the installed app larger. An app bundle (AAB) is not concerned: Google Play builds and aligns the APKs.
Check before you submit
Upload the APK, AAB or split-APK set (XAPK, APKS, APKM) on the store check page. It runs PLAY-16KB-ELF PLAY-16KB-ZIPALIGN against the dates on this page, then deletes the file: nothing about the app is kept. The same engine runs offline in the Narvy CLI, and exits with code 1 when a blocker is found, so it can gate a CI job.
Google's own commands give the same answer: zipalign -c -P 16 -v 4 app.apk for an APK, bundletool dump config --bundle=app.aab | grep alignment for a bundle (expect PAGE_ALIGNMENT_16K).
narvy store-check app-release.aabFAQ
My app has no C or C++ code. Why is it flagged?
Because a dependency ships a native library. Look at the paths in the report (lib/arm64-v8a/lib*.so): each one comes from an SDK or framework in your build.
Does the 32-bit armeabi-v7a library need to be aligned?
No. The requirement is about 64-bit devices, so only arm64-v8a and x86_64 libraries are checked.
I upload an app bundle. Does zip alignment matter?
No: Google Play generates the APKs from the bundle and aligns them itself, so the store check marks the zip alignment as not applicable. The ELF alignment of each library still matters.