Android System Back Button Closes the App After Upgrading to Target SDK 36 — React Native Fix

●1 ●3
calendar_today ago • schedule8 min read
— Originally published at dev.to

If you're maintaining a React Native Android application and recently upgraded your project to target SDK 36 (Android 16), you may encounter an unexpected navigation issue:

Pressing the Android system back button closes the app instead of navigating to the previous screen.

This can be particularly confusing when React Navigation is already configured correctly and the same navigation flow works perfectly on older Android target SDK versions.

This article explains what changed, how to identify the issue, the workaround I used, and what you should consider for a proper Android 16 migration.


The Problem

After upgrading the Android project from an older target SDK to:

targetSdkVersion = 36

the app started behaving differently when using the Android system back button.

For example, suppose the navigation stack is:

Home
  ↓
Products
  ↓
Product Details

When the user presses the Android system back button from Product Details, the expected behavior is:

Product Details
        ↓
    Products

Instead, the application could close.

Interestingly, navigation using React Navigation itself continued to work:

navigation.goBack();

The issue was specifically related to the Android system back event.


Environment

The issue was observed in a React Native application with a setup similar to:

React Native
React Navigation
Android SDK 36
Target SDK 36

The important change was upgrading the Android target SDK to API level 36, corresponding to Android 16.


Why Does This Happen?

The important part of the migration is the Android back-navigation change.

Android has been moving away from the older:

onBackPressed()

mechanism toward the newer:

OnBackInvokedDispatcher

and predictive back navigation APIs.

With newer Android versions and target SDK requirements, applications need to properly participate in the newer back-navigation system.

This can expose compatibility issues in applications or libraries that still rely on the older back handling mechanism.

In a React Native application, the Android system back event eventually needs to be correctly propagated into the React Native / React Navigation layer.

If that doesn't happen, Android may interpret the back action as:

No navigation handler
        ↓
Finish current Activity
        ↓
App closes

instead of:

System Back
     ↓
React Native Back Handler
     ↓
React Navigation
     ↓
Previous screen

How I Identified the Problem

The first thing I checked was whether React Navigation itself was working.

Navigation from the application was working correctly:

navigation.navigate("ProductDetails");

and programmatic back navigation also worked:

navigation.goBack();

The problem only occurred when pressing the physical/system Android back button.

I also checked whether the application was closing directly from the Home screen.

That behavior is expected:

Home
 ↓
Android Back
 ↓
App exits

The actual problem was:

Home
 ↓
Product List
 ↓
Product Details
 ↓
Android Back
 ↓
App exits ❌

instead of:

Home
 ↓
Product List
 ↓
Product Details
 ↓
Android Back
 ↓
Product List ✅

This distinction is important when debugging Android back navigation.


The AndroidManifest Configuration

The Android application can control the behavior of the newer back system using:

android:enableOnBackInvokedCallback

For example:

<application
    android:name=".MainApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:enableOnBackInvokedCallback="false">

In my case, setting:

android:enableOnBackInvokedCallback="false"

worked as a temporary workaround.

After adding this configuration, the Android system back button once again started navigating to the previous React Navigation screen instead of immediately closing the application.


Why Does false Work?

Setting:

android:enableOnBackInvokedCallback="false"

essentially disables the application's participation in the newer OnBackInvokedDispatcher behavior.

This allows the application to continue using the older back handling path.

Conceptually:

Without the workaround

Android System Back
        ↓
OnBackInvokedDispatcher
        ↓
React Native / Navigation handler
        ↓
❌ Handler not properly triggered
        ↓
Activity finishes
        ↓
App closes

With the temporary workaround

Android System Back
        ↓
Legacy back handling
        ↓
React Native BackHandler
        ↓
React Navigation
        ↓
Previous screen

So the workaround doesn't really "fix" predictive back support.

It tells Android to avoid the newer callback behavior for this application.


Is enableOnBackInvokedCallback="false" the Permanent Fix?

Not necessarily.

This is an important distinction.

If your application is targeting Android 16, you should ideally investigate whether your React Native version and navigation dependencies properly support Android's newer back-navigation behavior.

Using:

android:enableOnBackInvokedCallback="false"

can be useful as a compatibility workaround while migrating, but it should not automatically be considered the final Android 16 solution.

The long-term goal should be:

Android 16
      ↓
Predictive Back
      ↓
OnBackInvokedDispatcher
      ↓
React Native
      ↓
React Navigation

working correctly.


Check Your React Native Version

Before adding application-level workarounds, check the React Native version:

npm list react-native

or:

yarn why react-native

Also check React Navigation:

npm list @react-navigation/native

For example:

react-native
@react-navigation/native
@react-navigation/native-stack
@react-navigation/bottom-tabs

Older combinations may have different levels of Android predictive-back support.

It's important to evaluate the complete dependency chain rather than changing only the AndroidManifest.


Check Your MainActivity

Also inspect your Android MainActivity.

A typical React Native application may have something similar to:

public class MainActivity extends ReactActivity {

    @Override
    protected String getMainComponentName() {
        return "MyApp";
    }
}

If your application has custom back handling, search the Android project for:

onBackPressed

For example:

grep -R "onBackPressed" android/

Also search for:

OnBackInvokedDispatcher

and:

OnBackInvokedCallback

This helps identify whether custom native code is interfering with the new Android back-navigation mechanism.


Check React Native BackHandler

React Native applications can listen for Android back events using:

import { BackHandler } from "react-native";

For example:

useEffect(() => {
  const subscription = BackHandler.addEventListener(
    "hardwareBackPress",
    () => {
      navigation.goBack();
      return true;
    }
  );

  return () => subscription.remove();
}, [navigation]);

However, don't add this globally just to hide the problem.

React Navigation normally handles Android back navigation for its navigation stack.

Adding multiple global BackHandler listeners can introduce new problems such as:

  • Back event being consumed too early
  • Incorrect navigation
  • Screens being popped multiple times
  • Modals not closing correctly
  • Navigation stack becoming inconsistent

So first determine whether the underlying Android back event is reaching React Native correctly.


A Useful Debugging Test

You can temporarily add a BackHandler listener to determine whether React Native receives the system back event:

useEffect(() => {
  const subscription = BackHandler.addEventListener(
    "hardwareBackPress",
    () => {
      console.log("ANDROID BACK EVENT RECEIVED");

      return false;
    }
  );

  return () => subscription.remove();
}, []);

Then navigate to a screen and press the Android system back button.

If you see:

ANDROID BACK EVENT RECEIVED

then the event is reaching React Native.

If the app closes without the event reaching your JavaScript handler, the problem is likely further down in the Android back-dispatching path.

This is a useful way to separate:

Android back event problem

from:

React Navigation configuration problem

Don't Confuse Home Screen Behavior With a Bug

One important testing detail:

If the user is already on the root screen:

Home

pressing Android Back is normally expected to exit the application.

For example:

Home
 ↓
Android Back
 ↓
App closes

That alone isn't evidence of a problem.

The important test is:

Home
 ↓
Screen A
 ↓
Screen B
 ↓
Android Back

Expected:

Screen B
 ↓
Screen A

If instead:

Screen B
 ↓
App closes

then back navigation is not being handled correctly.


Testing Checklist After Target SDK 36 Upgrade

After upgrading to API 36, I recommend testing all of these scenarios.

1. Normal navigation

Home → List → Details

Press system Back.

Expected:

Details → List

2. Multiple navigation levels

Home → A → B → C

Press Back repeatedly.

Expected:

C → B → A → Home

3. Root screen

Home

Press Back.

Expected:

App exits

4. Modal

Open a modal and press Back.

Expected:

Modal closes

instead of:

App exits

5. Bottom tabs

Test:

Tab A → Tab B → Screen

and verify that system Back behaves consistently with your navigation design.


6. Authentication flow

Test:

Login → OTP → Home

and make sure Back doesn't allow users to incorrectly return to authentication screens.


Test:

Deep Link → Details

and verify the back stack behaves as expected.


8. Android gesture navigation

Test using:

  • 3-button navigation
  • Gesture navigation

Predictive back behavior can differ from traditional button-based testing, so both should be tested.


Temporary Workaround

If your application is currently affected and you need to stabilize the release, one possible temporary configuration is:

<application
    ...
    android:enableOnBackInvokedCallback="false">

After rebuilding the application:

cd android
./gradlew clean
cd ..

Then rebuild:

npx react-native run-android

or use your normal release build process.

For an Expo bare/prebuild project, make sure the generated Android configuration is also correctly reflected in the source configuration you use for builds, rather than relying on a manual change that can be overwritten.


Instead of treating the manifest flag as the final solution, I recommend approaching the migration in this order:

1. Upgrade target SDK → 36
          ↓
2. Test system Back
          ↓
3. Check React Native version
          ↓
4. Check React Navigation versions
          ↓
5. Search for custom Android back handling
          ↓
6. Search for BackHandler overrides
          ↓
7. Test predictive back
          ↓
8. Update incompatible dependencies
          ↓
9. Use manifest workaround if required
          ↓
10. Remove workaround after proper migration

This approach makes it easier to identify the actual compatibility problem.


Important Takeaway

Upgrading:

targetSdkVersion

is not always just a build configuration change.

A target SDK upgrade can activate or expose new Android platform behavior.

For Android 16 / API 36, back navigation and predictive back behavior are especially important areas to test.

If your React Native app suddenly starts closing when the Android system back button is pressed after moving to target SDK 36, don't immediately assume that your React Navigation stack is broken.

First determine whether:

Android
   ↓
Back Dispatcher
   ↓
React Native
   ↓
React Navigation

is working correctly.

The following configuration can serve as a temporary compatibility workaround:

android:enableOnBackInvokedCallback="false"

but the preferred long-term solution is to ensure that the React Native and navigation stack properly supports Android's modern back-navigation APIs.


Final Checklist

Before releasing a target SDK 36 build, verify:

  • [ ] Android system Back navigates correctly
  • [ ] Root screen exits correctly
  • [ ] Nested navigation works
  • [ ] Modals handle Back correctly
  • [ ] Bottom tabs behave correctly
  • [ ] Authentication screens behave correctly
  • [ ] Deep links create the expected back stack
  • [ ] Gesture navigation works
  • [ ] 3-button navigation works
  • [ ] Predictive back behavior has been tested
  • [ ] React Native version is compatible
  • [ ] React Navigation dependencies are compatible
  • [ ] Custom BackHandler logic has been reviewed
  • [ ] Native onBackPressed() implementations have been reviewed
  • [ ] OnBackInvokedDispatcher usage has been reviewed
  • [ ] Any temporary enableOnBackInvokedCallback workaround is documented

Conclusion

Android 16 introduces another step in the evolution of Android back navigation. For React Native applications, upgrading to target SDK 36 can expose problems where the system Back button no longer reaches the JavaScript navigation layer as expected.

If your app starts closing instead of navigating backward, investigate the new Android back-dispatching behavior before modifying your navigation stack.

A manifest-level workaround such as:

android:enableOnBackInvokedCallback="false"

may restore the previous behavior temporarily, but dependency compatibility and proper predictive-back support should be addressed as part of the complete migration.

Target SDK upgrades should always be followed by dedicated navigation regression testing—not just build and installation testing.


✍️ Written by Dainy Jose — React Native Mobile Application Developer with 3+ years of experience building cross-platform mobile apps using React Native (Expo, TypeScript, Redux).
Currently expanding backend knowledge through the MERN Stack (MongoDB, Express.js, React.js, Node.js) to create more efficient, full-stack mobile experiences.

Tech Stack: React Native · TypeScript · Redux · Expo · Firebase · Node.js · Express.js · MongoDB · REST API · JWT · Jest · Google Maps · Razorpay · PayU · Agile · SDLC · Git · Bitbucket · Jira

Connect with me:
Portfolio
LinkedIn
GitHub

1 Comment

0 votes
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

React Native Quote Audit - USA

kajolshah - Mar 2

React Native Android build failed: what I would check first

Asta Silva - Apr 6

3.5 best practices on how to prevent debugging

Codeac.io - Dec 18, 2025

How to save time while debugging

Codeac.io - Dec 11, 2025

How to fix `global._getAnimationTimestamp is not a function` After Upgrading to Expo SDK 55

Asta Silva - Jul 16
chevron_left
133 Points • 4 Badges
Bangalore, Karnataka • dainyjose.github.io/my-portfolio
1Posts
0Comments
1Connections
Senior Software Developer specializing in React Native, TypeScript, and cross-platform mobile develo... Show more

Related Jobs

View all jobs →

Commenters (This Week)

6 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!