If you opened Play Console recently and found a warning that your app must target Android 16 (API level 36), this is what it means, what it will break, and the order to fix it in.
The short version: since 31 August 2026, Google Play will not accept a new app or an app update unless it targets API 36. Your live listing does not disappear. But the next time you need to ship anything — a feature, a price change, an urgent fix for a crash — the upload is refused until the target is raised.
And raising it is not the one-line change it looks like.
What the rule actually does
Play’s requirement has two parts, and they apply to different things:
- New apps and updates must target Android 16 (API 36) or higher.
- Existing apps must target at least Android 15 (API 35) to stay available to new users on newer devices. Below that, Play says the app will stop being available to new users whose devices run an Android version higher than the app’s target. People who already installed it can still reinstall and use it.
An extension to 1 November 2026 can be requested from the Policy status page in Play Console. It has to be requested and approved; it is not automatic.
After August 31, 2026: what your latest target API level still allows
| Your latest release | People who already installed it | New people installing it | You shipping an update or fix |
|---|---|---|---|
| Targets API 36 | Yes | Yes, on every Android version | Yes |
| Targets API 35 | Yes | Yes, on every Android version | No — until it targets 36, or November 1, 2026 with an approved extension |
| Targets API 34 or lower | Yes — they can still reinstall it | Only on devices running Android no newer than the app’s target | No |
The middle row is where most apps are sitting today. An app on API 35 is fully available in the store, so nothing looks wrong — until the day it needs an update.
Why “change 34 to 36” is not the fix
The target SDK is not a label. It is a behaviour switch. Android keeps old behaviour for apps that target old versions, and applies each version’s changes only when an app declares it is ready for them. Raising the number is that declaration.
So the Gradle change itself really is two lines:
android {
compileSdk = 36
defaultConfig {
targetSdk = 36
}
}
What those two lines switch on is the rest of this post. An app coming from API 34 takes on both Android 15’s changes and Android 16’s in one release — which is the usual situation for an app nobody has touched in a year.
Change 1: every screen goes edge-to-edge
This is the change you will see first, on every screen, on day one.
From API 35, apps are edge-to-edge by default: the status bar and gesture navigation
bar become transparent, and your layout no longer stops at them. setStatusBarColor()
stops having any effect. Android 15 allowed an opt-out attribute,
windowOptOutEdgeToEdgeEnforcement, and plenty of apps used it to defer the work.
On API 36 that attribute is deprecated and disabled. There is no longer a switch.
What that looks like in a real app: the screen title slides under the clock, the bottom “Pay” or “Save” button lands under the gesture bar where a swipe sends the user home instead, and full-screen sheets lose their bottom row. It rarely crashes, so crash reporting will not tell you. Screenshots will.
The fix: apply insets, not colours
The pattern Android’s own templates use — enable edge-to-edge, then pad the views that must stay clear by the size of the system bars:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { view, insets ->
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
view.setPadding(bars.left, bars.top, bars.right, bars.bottom)
insets
}
}
}
The judgement is per screen, and that is where the time goes. Backgrounds, maps, images and scrolling lists usually should run behind the bars. Titles, buttons, text fields and anything tappable should not. Padding the root of every screen is the fast fix and looks noticeably worse than doing it properly.
In React Native, the legacy <SafeAreaView> is deprecated as of 0.81; the
replacement is react-native-safe-area-context. In Flutter, the equivalent is
SafeArea or the padding from MediaQuery. Flutter’s own note warns that its opt-out
might crash your app on Android 16 or later, so if your project still has it, that is
the first thing to remove.
Change 2: your back button handler stops being called
This one is quieter and more dangerous, because it fails without an error.
For apps targeting API 36, predictive back is on by default, and Android’s wording is
exact: onBackPressed() is not called and KEYCODE_BACK is not dispatched.
Anything the app did in that override simply stops happening. The common cases:
- “You have unsaved changes — discard?” dialogs. The user swipes back and the draft is gone.
- Closing a custom drawer, search overlay or bottom sheet before leaving the screen.
- Stepping back through a multi-step form or checkout instead of exiting it.
- Blocking back during a payment in progress.
The fix: decide before the gesture, not during it
The replacement is a callback registered with the back dispatcher. The important difference is conceptual: with predictive back, the system starts animating as the gesture begins, so your app must already know whether it wants to intercept. You enable and disable the callback as state changes, not when back is pressed:
private val discardDraft = object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
showDiscardDialog()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onBackPressedDispatcher.addCallback(this, discardDraft)
}
// Wherever the draft changes:
discardDraft.isEnabled = hasUnsavedChanges
A temporary opt-out exists — android:enableOnBackInvokedCallback="false" on the
application or activity. Android describes it as temporary. Use it to ship an urgent
update if you must, and schedule the migration in the same breath.
For React Native, the 0.81 release notes say BackHandler keeps working for most
cases, but custom native code that overrides onBackPressed() needs migrating — which
includes native modules and third-party libraries, not just your own code. Expo SDK 54
leaves predictive back disabled by default, so an Expo app will not see this until it
is switched on.
Change 3: tablets and foldables ignore your orientation lock
Many apps lock themselves to portrait and assume that settles the question of layout. On API 36, for large screens, it no longer does.
On any display at least 600dp wide — tablets, and foldables when unfolded — apps
targeting API 36 have screenOrientation, resizableActivity, minAspectRatio and
maxAspectRatio ignored, along with setRequestedOrientation(). The window fills the
screen and rotates with the device. Games are exempt, and phones below 600dp are
unaffected.
There is an opt-out property, PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY. Android
is explicit that it stops working when you target API 37. If Play keeps raising its
requirement once a year, as it has, that is roughly a year of runway — our reading,
not a date Android has published.
Two things make this worse than it sounds. First, rotation now happens, and rotation recreates the activity — any state the app was not saving because “we’re portrait-only” is lost on the turn. Second, the stretched layout is what reviewers and users on those devices see, in screenshots and in reviews.
Change 4: the Android 15 changes you may have skipped
If the app jumps straight from 34, it also inherits everything below. These are the ones that turn up most in real apps — not Android’s full list.
Inherited from API 35: changes you get if you skipped a year
| Change | What you would see | Impact |
|---|---|---|
| LayoutEdge-to-edge is enforcedContent draws behind the status and navigation bars unless the app applies insets. setStatusBarColor() has no effect. | Headers under the clock, buttons under the gesture bar | Breaks |
| LayoutscreenWidthDp and screenHeightDp include the system barsConfiguration sizes no longer exclude the bars, so size maths done by hand is off. | Breakpoints and custom sizing shift by the bar height | Degrades |
| NetworkingTLS 1.0 and 1.1 are disallowedConnections to servers that only speak the old versions fail. | An old API or payment endpoint stops responding | Breaks |
| Background workdataSync foreground services capped at 6 hours per 24onTimeout() is called and the service must stop within seconds; starting it again after the limit throws. | Long uploads or syncs die part-way | Degrades |
| Background workBOOT_COMPLETED cannot start several foreground service typesdataSync, camera, mediaPlayback, phoneCall, mediaProjection and microphone throw instead. | A crash on boot that never happens in testing | Degrades |
| MediaAudio focus requires being the top app or a foreground serviceOtherwise requestAudioFocus returns AUDIOFOCUS_REQUEST_FAILED. | Playback silently refuses to start | Degrades |
| Java runtimeString.format argument index 0 now throwsIllegalFormatArgumentIndexException — indices start at 1. | A crash on a screen that formats text | Degrades |
| Java runtimeKotlin removeFirst() / removeLast() resolve to new Java methodsCompiled against SDK 35, they throw NoSuchMethodError on Android 14 and below. | Crashes only on older phones — the ones you did not test | Breaks |
| TextelegantTextHeight defaults to trueAffects Arabic, Thai, Tamil and several other scripts; in Android 16 the attribute is ignored. | Clipped or re-spaced text in some languages | Cosmetic |
Two deserve a highlight because they fail somewhere you are not looking. TLS 1.0 and
1.1 are disallowed, so an old payment gateway, CMS or internal API that nobody has
upgraded simply stops answering. And Kotlin’s removeFirst() and removeLast(), compiled
against SDK 35, throw NoSuchMethodError on Android 14 and older — so the crash only
appears on older phones, which are exactly the ones a small team does not test on.
Also on the calendar: 16 KB memory pages
A separate Play requirement applies to apps with native code — C or C++, the NDK, or a third-party native library, which covers a lot of React Native, Flutter, Unity, media and security SDKs. Apps targeting API 35 and higher must support 16 KB memory pages on 64-bit devices. Per Android’s page-size guide, from 1 February 2027, updates that do not support it cannot be released.
This deadline has moved more than once, so check the date Play Console shows for your own app. Apps written only in Java or Kotlin are unaffected. Android Gradle Plugin 8.5.1 and NDK r28 or newer build aligned by default; React Native’s 0.81 notes state that React Native itself is already compliant, but every native dependency still has to be. To check a release build:
zipalign -v -c -P 16 4 app-release.apk
Where each framework stands
If your app is built with a cross-platform framework, the framework version decides your starting point — but not your finishing point.
Framework status for Android 16
| React Native | Expo | Flutter | |
|---|---|---|---|
| Version | 0.81 | SDK 54 | 3.27 and later |
| Default target | Android 16 (API 36) by default | Android 16 (ships React Native 0.81) | 3.27 made Android 15 (API 35) the default target — confirm what your version resolves flutter.targetSdkVersion to |
| Edge-to-edge | Required on Android 16; new edgeToEdgeEnabled Gradle property extends it to older versions | Enabled in all Android apps and cannot be disabled | Edge-to-edge is the default from API 35; Flutter warns the opt-out might crash your app on Android 16 or later |
| Back gesture | Predictive back on by default for API 36; BackHandler keeps working, custom onBackPressed() overrides need migrating | Predictive back disabled by default in SDK 54; enable it in app.json | Not covered by the Flutter breaking-change note — audit plugins and native code that override onBackPressed() |
| Watch for | Legacy <SafeAreaView> deprecated — move to react-native-safe-area-context | react-native-edge-to-edge is no longer an expo dependency | If you opted out, move the attribute into a values-35 resource folder, or migrate to edge-to-edge |
The common misunderstanding here is that upgrading the framework is the fix. It sets the target. It does not decide which of your screens should pad for the status bar, move your custom back handling, or make your native modules and plugins compliant. And a framework upgrade that spans several versions — React Native in particular — usually brings its own breaking changes along with the ones above.
The order to do it in
- Check where you actually stand. Open Play Console’s Policy status page, confirm your current target, and request the November extension now if a release is due before the fix will be ready. It costs nothing.
- Upgrade the framework, then raise the target on a branch — not in the same commit as feature work.
- Walk every screen for edge-to-edge, on gesture navigation and three-button navigation, with a display cutout. Screenshot each one.
- Search the codebase and dependencies for
onBackPressedand migrate each use. Then test every flow where back should not simply leave the screen. - Run it on a large-screen emulator and a foldable. Rotate on every screen with unsaved input.
- Test on an Android 14 device, specifically for the Kotlin collection crash and TLS failures against your real backend.
- Check native libraries for 16 KB alignment while you are in the build anyway.
- Release through a staged rollout and watch crash and ANR rates for the first days — Play’s vitals thresholds apply to the new build from the moment it ships.
How long that takes depends almost entirely on step 3 and on how far behind the framework version is. In our experience, an app already on a recent framework release with a dozen screens is days of work; an app several major versions behind, with custom native modules and a portrait-only design, is weeks. Those are our estimates, not measurements.
If you would rather not do this yourself
This is exactly the kind of work that lands on a team that is busy shipping features: it arrives on a date nobody chose, it touches every screen, and it looks finished long before it is. It is also the work we do most often for existing apps — framework upgrades, platform deadlines and the release that follows, as part of our mobile app development and maintenance.
If your app was built quickly or by a previous team, the upgrade tends to surface other problems at the same time; what usually needs fixing in AI-built apps covers those. And iOS has its own deadline coming, where apps built with the iOS 27 SDK must use the scene life cycle or fail to launch.
Send us your Play Store link and the framework you are on, and we will tell you what the upgrade involves and how long it should take — get in touch.