The Requirement Hiding in Your Dependency Tree
.so files inside their AARs. And the guide is blunt about what happens to them: "If your app uses any NDK libraries, either directly or indirectly through an SDK, then you will need to rebuild your app for it to work on these 16 KB devices."
The first task is therefore not engineering. It is an inventory: open your release APK and look in lib/. Every .so in arm64-v8a and x86_64 is a dependency with a deadline.Why Android Is Changing Its Page Size
| Measurement on 16 KB devices | Improvement Google reports |
|---|---|
| App launch under memory pressure | "3.16% lower on average, with more significant improvements (up to 30%) for some apps that we tested" |
| Power draw during app launch | "4.56% reduction on average" |
| Camera launch | "4.48% faster hot starts on average, and 6.60% faster cold starts on average" |
| System boot | "improved by 8% (approximately 950 milliseconds) on average" |
What Actually Breaks
PAGE_SIZE macro as a constant, breaks at run time. The guide's instruction: look for code that assumes "a device's page size is 4 KB (4096). Use getpagesize() or sysconf(_SC_PAGESIZE) instead," and audit mmap() calls with page-aligned arguments. It also notes that "PAGE_SIZE is undefined when 16 KB mode is enabled on NDK r27 and higher," so some of this surfaces as compile errors, which is the good outcome.
Android does have a safety net, and you should not rely on it. On a 16 KB device, the package manager can run an app with 4 KB-aligned libraries in a backcompat mode, and "the app displays a warning when it's first launched saying that it's running in 16 KB backcompat mode." A warning dialog on first launch is a bug report your users file on your behalf.Find It Before Google Play Does
llvm-objdump -p on each .so for segment alignment; zipalign -c -P 16 -v 4 on the APK for zip alignment; Google also links a check_elf_alignment.sh script that runs both.
- Play Console. The App Bundle Explorer reports "your app's build compliance" and "guidance on where your app may need updating."
- A real 16 KB runtime. The SDK Manager offers 16 KB emulator images for ARM64 and x86_64, and on Pixel 8, 8 Pro and 8a (Android 15 QPR1 or higher) and Pixel 9-series devices a developer option boots the device in 16 KB mode. Confirm with adb shell getconf PAGE_SIZE, which "should return a value of 16384."
The cheapest insurance is a CI gate, so a dependency upgrade that pulls in a misaligned library fails the pull request instead of the Play upload. The script below uses only the two documented checks.#!/usr/bin/env bash
# CI gate: fail if any 64-bit native library is not 16 KB aligned.
set -euo pipefail
APK=app/build/outputs/apk/release/app-release.apk
OBJDUMP="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump"
WORK=$(mktemp -d)
bad=0
# 1. ELF segment alignment: every LOAD segment must be 2**14 (16 KB) or larger.
unzip -q "$APK" 'lib/arm64-v8a/*' 'lib/x86_64/*' -d "$WORK" || true
for so in "$WORK"/lib/*/*.so; do
[ -e "$so" ] || continue
if "$OBJDUMP" -p "$so" | awk '$1 == "LOAD" && $NF != "2**14" && $NF != "2**16" { hit = 1 } END { exit !hit }'; then
echo "NOT 16 KB ALIGNED: $(basename "$so")"
bad=1
fi
done
# 2. Zip alignment of uncompressed libraries, exactly as the Android docs check it.
if ! zipalign -c -P 16 -v 4 "$APK" > /dev/null; then
echo "zip alignment check failed"
bad=1
fi
exit $badFix It in Order: Toolchain, Dependencies, Code
-Wl,-z,max-page-size=16384 and -Wl,-z,common-page-size=16384. If you cannot upgrade AGP past 8.5, the documented fallback is to "switch to use compressed shared libraries" with useLegacyPackaging, which avoids zip alignment at the cost of install size and load time.
Dependencies second, because you cannot fix them yourself. A prebuilt .so inside a vendor SDK can only be realigned by recompiling it, and you do not have its source. Map every misaligned library to the SDK that ships it, check each vendor's release notes for a 16 KB-compatible version, and escalate the ones without one now. Vendors facing the same deadline across their whole customer base will prioritise the customers who are asking. An SDK with no fix and no roadmap is a replacement decision, and replacement decisions take a quarter.
Your own native code last, because it is the part you control. Rebuild with the current NDK, then search for 4096, PAGE_SIZE and mmap. Test on a 16 KB emulator image, not just by reading alignment tables: a correctly aligned library can still carry a hard-coded page size in its logic.// build.gradle.kts: fallback ONLY if AGP cannot be upgraded past 8.5
android {
packaging {
jniLibs {
useLegacyPackaging = true // compressed libs: no zip alignment, larger installs
}
}
}
/* CMakeLists.txt: only needed on NDK r27 or lower (r28+ aligns to 16 KB by default)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
"-Wl,-z,max-page-size=16384"
"-Wl,-z,common-page-size=16384"
)
*/Four Months Is Less Time Than It Sounds
.so in your release APK and the dependency that ships it. That list is the whole project.
2. This sprint: toolchain. AGP 8.5.1 or later, NDK r28 or later, and the CI gate above on every pull request.
3. This month: vendors. A ticket per SDK that ships a misaligned library, with a named owner and a date. Chase the ones with no answer.
4. Next month: test on 16 KB. Emulator image in CI, a Pixel in 16 KB mode on the QA desk, and a manual pass over the flows that exercise native code: camera, media, ML, maps, payments.
5. Before January: ship it. Release the aligned build behind a staged rollout well before the deadline, so the release that proves compliance is not also the release that carries a new feature.
The teams that will scramble in January are the ones who answered "we don't have native code" in September. Open the APK.Key Takeaways
- 1Google Play will block app updates that do not support 16 KB memory page sizes from February 1, 2027, for apps targeting Android 15 and higher.
- 2Pure Kotlin and Java apps are exempt only if every library and SDK is also free of native code; most production apps ship .so files from third-party SDKs.
- 3Three things break: ELF LOAD segments aligned below 2**14, uncompressed libraries not 16 KB zip-aligned, and native code that assumes a 4096-byte page.
- 4AGP 8.5.1+ and NDK r28+ make your own builds 16 KB compatible by default; on AGP 8.3 to 8.5 an app can pass locally and fail to install from Play.
- 5Prebuilt libraries inside vendor SDKs can only be fixed by the vendor; inventory them and escalate now.
- 6Gate CI with llvm-objdump and zipalign -c -P 16, and test on a 16 KB emulator image or a Pixel in 16 KB mode.
Frequently Asked
Does a Kotlin-only Android app need to support 16 KB pages?
Only if no library or SDK it includes ships native code. Google’s guide exempts apps that use only Java or Kotlin "including all libraries or SDKs"; check the lib/ folder of your APK for .so files.
What is the 16 KB deadline on Google Play?
Google’s page size guide states that from February 1, 2027, app updates that do not support 16 KB memory page sizes cannot be released, for apps targeting Android 15 (API 35) and higher.
Which tool versions support 16 KB pages by default?
AGP 8.5.1 or higher zip-aligns uncompressed native libraries to 16 KB, and NDK r28 or higher compiles 16 KB-aligned libraries by default. Older NDKs need the -z max-page-size=16384 linker flags.
Ready to architect your next Android app?
ANDROID-ARCHITECT generates production-ready Kotlin code, architecture blueprints, and CI/CD configurations from plain-language descriptions. Start building for free.