Skip to content
Malik Hamza Shabbir
Mobile Engineeringreact nativeandroidexpogoogle play

Your React Native App Will Break on Google Play August 31, 2026: The Target API 36 Migration Checklist

HSMalik Hamza ShabbirUpdated 8 min read

In short

Google Play makes target API level 36 (Android 16) mandatory for new apps and updates on August 31, 2026. The hard part is not the version bump, it is that API 36 forces edge-to-edge display and predictive back, which silently break layouts and navigation. Audit your insets and BackHandler usage, then verify on a real Android 16 build before the cutoff. See my mobile development work if you want it handled.

Your React Native App Will Break on Google Play August 31, 2026: The Target API 36 Migration Checklist
On this page

Google Play makes target API level 36 (Android 16) mandatory for all new apps and app updates on August 31, 2026. If your React Native or Expo app still targets API 35 or lower after that date, the Play Console will block your release. The bigger surprise is not the version bump itself. It is that Android 16 forces edge-to-edge display and changes predictive back behavior, and both of those can silently break layouts in an app that built and ran fine the day before. Here is the triage checklist I run when I bump targetSdkVersion to 36 on a New Architecture RN or Expo project, and how I verify it in EAS before the cutoff.

What exactly is changing on August 31, 2026?

Google Play requires that new apps and app updates target API level 36 (Android 16) by August 31, 2026. After that date you cannot submit an update that targets a lower level, and the Play Console shows a warning banner on existing apps until you comply.

This is the same annual ratchet Google has run for years. Each new Android release becomes the required target one cycle later. The catch with API 36 is what comes bundled into it. When your app targets 36, Android stops treating two behaviors as opt-in and starts enforcing them: edge-to-edge display and predictive back navigation. Targeting 36 is the switch that turns both on. You do not get to bump the number and ignore the consequences.

A few clarifications I have to make on almost every client call:

  • This is a target level, not a minimum. Your minSdkVersion stays where it is, so older devices are not dropped.

  • Targeting 36 does not require Android 16 on the build machine in the way you might fear. You need compileSdkVersion 36 and the Android 16 SDK installed, which is handled for you on EAS.

  • An app that already passed review does not get pulled. You just cannot ship a new update until you comply.


Why does targetSdkVersion 36 break my layout when nothing else changed?

Because targeting API 36 forces edge-to-edge display, your content is now drawn behind the status bar and the navigation bar instead of being letterboxed inside them. Views that used to sit in a safe rectangle suddenly have their top and bottom edges hidden under system UI.

This is the single most common breakage I see during app-rescue work. The symptoms look like a regression in your own code even though you changed nothing in your screens:

  • A header or top tab bar tucked under the status bar clock.

  • A bottom navigation row or a submit button overlapping the gesture handle.

  • A modal that no longer respects the notch.


On older targets you could call setStatusBarTranslucent(false) or rely on the system insetting your window. On API 36 that escape hatch is gone for the status bar and navigation bar. The fix is to handle insets yourself, which in the React Native world means react-native-safe-area-context.

If you are on Expo SDK 52 or newer, edge-to-edge is already the default and react-native-safe-area-context ships in the template, so you may have less to do. On a bare RN app that predates this, you almost certainly have screens written before insets mattered.

Here is the pattern I standardize on. Wrap the app once in the provider, then consume insets where they matter.

TSX
// App.tsx
import { SafeAreaProvider } from 'react-native-safe-area-context';

export default function App() {
  return (
    <SafeAreaProvider>
      <RootNavigator />
    </SafeAreaProvider>
  );
}

TSX
// A screen that used to assume the system inset for it
import { useSafeAreaInsets } from 'react-native-safe-area-context';

function HomeScreen() {
  const insets = useSafeAreaInsets();
  return (
    <View
      style={{
        flex: 1,
        paddingTop: insets.top,
        paddingBottom: insets.bottom,
      }}
    >
      {/* content */}
    </View>
  );
}

A mistake I see constantly: people wrap every screen in and then also add paddingTop: insets.top somewhere up the tree, so the inset gets applied twice and the header sits too low. Pick one source of truth per edge. I prefer the useSafeAreaInsets hook for fine control on screens that scroll, and SafeAreaView only for simple static layouts.

The other half of edge-to-edge is the system bar appearance. Now that content draws behind the bars, you must set the bar content color yourself or your status bar icons can vanish into a light background.

TSX
import { StatusBar } from 'expo-status-bar';
// or react-native's StatusBar in bare projects
<StatusBar style="dark" />

What is predictive back and how does it break my app?

Predictive back is the Android 16 gesture that shows a peek of the previous screen (or the home screen) while the user is mid-swipe on the back gesture. When your app targets 36, the system treats your app as predictive-back ready, and if your navigation intercepts back the old way, the animation and the actual navigation can desync.

The classic failure is an app that uses BackHandler.addEventListener('hardwareBackPress', ...) to run custom logic, like closing a drawer or showing a confirmation dialog. With predictive back enforced, the user sees the system start its peek animation, then your handler fires and does something else, and the result feels broken or janky.

What I do during triage:

  • Audit every BackHandler listener. Most of them are doing work that React Navigation already handles. Delete the ones that are redundant.

  • For listeners you genuinely need (an unsaved-changes guard, for example), move to React Navigation's beforeRemove event or its usePreventRemove hook rather than the raw hardware handler.

  • Make sure you are on a recent React Navigation. The library added predictive-back support, so being current matters here.


TSX
import { usePreventRemove } from '@react-navigation/native';

function EditScreen({ navigation }) {
  const [dirty, setDirty] = React.useState(false);

  usePreventRemove(dirty, ({ data }) => {
    // show your "discard changes?" dialog, then:
    // navigation.dispatch(data.action) to proceed
  });

  // ...
}

In AndroidManifest.xml, the opt-in flag is android:enableOnBackInvokedCallback. On API 36 the platform behaves as predictive-back enabled regardless, but setting it true and testing against it is how you stop guessing.

What is the actual migration checklist?

Bump the target, then walk these in order: build config, edge-to-edge, predictive back, then library compatibility. Below is the table I keep pinned during a rescue.








AreaWhat to changeWhereRisk if skipped
Build configtargetSdkVersion and compileSdkVersion to 36android/build.gradle or Expo config pluginPlay Console blocks the release
Edge-to-edgeAdd insets via react-native-safe-area-contextApp root + screensHeaders/footers hidden under system UI
System barsSet bar content color explicitlyStatusBar componentInvisible status bar icons
Predictive backRemove redundant BackHandler, use beforeRemoveNavigation screensDesynced back animation
LibrariesUpdate to New Architecture compatible versionspackage.jsonNative crashes on launch
16 KB pagesConfirm native libs support 16 KB page sizeNative depsSeparate Play requirement

For a bare React Native app, the build config change lives in Gradle:

GRADLE
// android/build.gradle
buildscript {
  ext {
    buildToolsVersion = "36.0.0"
    minSdkVersion = 24
    compileSdkVersion = 36
    targetSdkVersion = 36
  }
}

For Expo, you set this through expo-build-properties rather than editing native files by hand:

JSON
// app.json
{
  "expo": {
    "plugins": [
      ["expo-build-properties", {
        "android": {
          "compileSdkVersion": 36,
          "targetSdkVersion": 36,
          "buildToolsVersion": "36.0.0"
        }
      }]
    ]
  }
}

One thing I want to be honest about: the cleanest path to API 36 compatibility is usually to be on a current React Native and Expo SDK in the first place. If you are stuck on an old version because of the legacy bridge, you have a bigger migration in front of you, and I wrote about exactly that in migrating a legacy app to 0.85 when New Architecture is the only option . Two of the other Play requirements often land in the same release window, so check them together: the 16 KB page size requirement for native libraries, and if you use animations, the Reanimated 4 and worklets migration since older Reanimated builds can be a New Architecture blocker.

How do I verify the bump in EAS before the cutoff?

Build a real artifact on EAS targeting 36, install it on a device or emulator running Android 16, and walk every screen plus the back gesture before you ever touch the Play Console. Local Metro debug builds will not catch edge-to-edge regressions reliably because release behavior and inset handling can differ.

My verification routine:

  1. Create a dedicated preview profile so I am not touching production builds while I test.


JSON
// eas.json
{
  "build": {
    "preview-api36": {
      "android": {
        "buildType": "apk",
        "gradleCommand": ":app:assembleRelease"
      },
      "distribution": "internal"
    }
  }
}

  1. Run the build and install on an Android 16 emulator image (API 36) from Android Studio.


BASH
eas build --profile preview-api36 --platform android

  1. Walk a manual checklist on the installed APK:

- Open every top-level screen and confirm headers clear the status bar.
- Confirm bottom tabs and any sticky CTA clear the navigation handle.
- Swipe the back gesture slowly on a few screens and watch for the predictive peek desyncing from your navigation.
- Rotate the device and check insets in landscape, which is where double-padding bugs show up.
- Confirm status bar icons are visible against your real backgrounds, light and dark.

  1. Only after that, push to an internal testing track in Play and confirm the API 36 warning banner clears.


I treat the EAS internal-distribution build as the source of truth. If it looks right there on a real Android 16 surface, it will look right in production. If you want this handled end to end rather than discovered the hard way after a rejected release, that is the kind of work I do under mobile development .

Do I have to do all of this if I am on a recent Expo SDK?

If you are already on Expo SDK 52 or newer with the New Architecture enabled, a lot of this is done for you, and your migration may be a target bump plus a layout audit rather than a rewrite. Edge-to-edge is the default in those templates and react-native-safe-area-context is already wired in.

Even then, do not assume. The forced edge-to-edge default still surfaces layout bugs in screens written by developers who had not internalized insets yet, and predictive back still trips custom BackHandler logic regardless of SDK version. The version you are on changes how much config work you do. It does not change the fact that you have to walk every screen on an Android 16 device and look.

The honest summary: the API 36 bump is a small change that drags two behavioral changes behind it. Budget your time for the layout and navigation audit, not the version number. If you would rather hand the triage to someone who has done it across several apps, my contact page is the place to start, and the more lead time before August 31 the calmer the migration is.

FAQ

When does target API 36 become mandatory on Google Play?

Google Play requires all new apps and app updates to target API level 36 (Android 16) by August 31, 2026, after which the Play Console blocks releases targeting a lower level.

Will my existing React Native app be removed if I miss the deadline?

No, your published app stays live, but you cannot ship any new update until it targets API 36.

Why does bumping targetSdkVersion to 36 break my layout?

Targeting API 36 forces edge-to-edge display, so your content draws behind the status and navigation bars and any view that relied on the system insetting it gets hidden under system UI.

What is predictive back and why does it affect my navigation?

Predictive back is the Android 16 gesture that previews the previous screen mid-swipe, and it desyncs when your app intercepts back with raw BackHandler listeners instead of React Navigation's beforeRemove.

How do I test the API 36 migration before submitting to Google Play?

Build an internal-distribution artifact on EAS targeting 36, install it on an Android 16 emulator or device, and walk every screen plus the back gesture before touching the Play Console.

Working on something like this?

I build web apps, AI features, and mobile products for clients. If this article matches a problem you have, tell me about it.

Start a conversation
HS

Malik Hamza Shabbir · Full-Stack & AI Engineer

I build full-stack and AI products solo: a reputation SaaS in production, RAG pipelines, and React Native apps. I write from what I ship, not from documentation summaries.

Related articles