Skip to content

Conversation

@Skalakid
Copy link
Contributor

@Skalakid Skalakid commented Jul 31, 2025

Description

This PR replaces the current workaround for crashes connected to the configuration changes on Android. The previous fix required disabling passing saved instance state in Activity onCreate - onCreate(null). Such a solution generates a problem with state persistence on the native side of brownfield applications. Because of that, we decided to replace it with a custom fragment factory that will limit the scope of the solution and fix the problem directly only on the React Native side. All fragments connected to the RN Screens package will be replaced with self-destructing ones, which will prevent Android from recreating the Fragment after the configuration change. We will leave this responsibility for React Native. Thanks to that, there won't be any conflict between the Android system and React Native, and we will prevent the app from crashing or any other app appearance-related issues.

Credits to @bojanlozanovski77 for bringing up the idea in #2917

Fixes: #17

Changes

  • Created a custom fragment factory (RNScreensFragmentFactory.kt) that won't instantiate RN Screens fragments
  • Created self-destructing fragments (NoOpFragment.kt) that will be instanciated by the RNScreensFragmentFactory, to prevent the conflict that crashes the app
  • Updated installation steps in library README
  • Applied the fix in MainActivity files of FabricExample and Example apps

Test code and steps to reproduce

  1. Remove ignoring config changes in AndroidManifest.xml file
<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
-   android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
    android:launchMode="singleTask"
    ...
  1. Launch the example app
  2. Verify if the app isn't crashing when causing different types of configuration changes on Android. For example:
    • Orientation change on devices ≥600dp with portrait lock
    • Opening/closing foldables or flip phones
    • Split/Multi-Window mode
    • Desktop windowing on tablets
    • Launching external activities (e.g. system Photo Picker)
    • Changing accessibility settings, permissions, system fonts, wallpapers, or language

Checklist

@Skalakid Skalakid changed the title fix: replace workaround for handling config changes on Android fix(Android): replace workaround for handling config changes Jul 31, 2025
@kkafar kkafar self-requested a review August 1, 2025 10:16
@kkafar kkafar self-assigned this Aug 1, 2025
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good overall. I have only few cosmetic changes requests.

I haven't tested the runtime though, will do when I tackle upgrade to 0.81.

Let's also give a credit to @bojanlozanovski77, who suggested this idea to us in the PR description. I see that you added him as co-author of commits - and that's awesome!


class RNScreensFragmentFactory : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return if (className.startsWith(BuildConfig.LIBRARY_PACKAGE_NAME)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this!

@Skalakid Skalakid marked this pull request as ready for review August 4, 2025 06:42
@kkafar kkafar force-pushed the @Skalakid/handle-config-changes-with-custom-fragments branch from 898b35d to 29de0d8 Compare August 30, 2025 12:36
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems that runtime works fine.

I've done some small refactors & will land this once the CI passes.

Thanks!

@kkafar kkafar changed the title fix(Android): replace workaround for handling config changes fix(Android): add custom fragment factory & modify library installation steps to prevent on-restoration crashes Aug 30, 2025
@kkafar kkafar merged commit 93cee67 into software-mansion:main Aug 30, 2025
7 checks passed
@bulkinav
Copy link

@Skalakid hello. I didn't quite understand from your example, do I need to leave this line in AndroidManifest.xml now?

android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"

@Skalakid
Copy link
Contributor Author

@bulkinav yes, you can leave this line as it is. I suggested removing it in the test steps to be able to test if the fix works and there aren't any crashes. If you remove this line, RN will lose its state during configuration changes. So in my opinion, the most common types should be specified there

@BasixKOR
Copy link

BasixKOR commented Oct 2, 2025

We saw a increased number of IllegalStateException about the fragement resotration after enabling the RNScreensFragmentFactory as the newer README suggested, and as far as I can see it should not cause any behaviour change if users continue to use super.onCreate(null). Is it correct?

I'll open a separate issue when I successfully reproduces the IllegalStateException, but for now I'm mainly looking for workaorunds.

@kkafar
Copy link
Member

kkafar commented Oct 2, 2025

This is correct. If this turns out to be problematic you can stay on super.onCreate(null). Will be grateful if you can come up with reproduction.

@darshak-k
Copy link

@Skalakid @kkafar Will the proposed solution preserve application state without having AndroidManifest configChanges ?

@kkafar
Copy link
Member

kkafar commented Nov 17, 2025

This is not a solution for preserving application state. Whether the state will be preserved or not depends on your particular application setup & how the react native is set up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android crashes nondeterministically when restoring from background

5 participants