facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.88k stars 24.3k forks source link

When Modal Component renders then AppState blur event listener calls in Android #36865

Open ims7inc opened 1 year ago

ims7inc commented 1 year ago

Description

When Modal/Alert component renders in our React Native App the App State goes blur

React Native Version

0.71.6

Output of npx react-native info

info Fetching system and libraries information... System: OS: macOS 12.6.1 CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz Memory: 81.42 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node Yarn: 1.22.0 - /usr/local/bin/yarn npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Managers: CocoaPods: 1.11.3 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: DriverKit 21.4, iOS 16.0, macOS 12.3, tvOS 16.0, watchOS 9.0 Android SDK: Not Found IDEs: Android Studio: 2021.2 AI-212.5712.43.2112.8512546 Xcode: 14.0.1/14A400 - /usr/bin/xcodebuild Languages: Java: 11.0.15 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: 0.71.6 => 0.71.6 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

When Modal/Alert component renders in our React Native App the App State goes blur

AppState.addEventListener('blur', callback);

here this callback method is triggering

Snack, code example, screenshot, or link to a repository

/**

`/**

github-actions[bot] commented 1 year ago
:warning: Unsupported Version of React Native
:information_source: It looks like your issue or the example you provided uses an unsupported version of React Native. Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please upgrade to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on StackOverflow to get further community support.
ims7inc commented 1 year ago

Same issue with latest React Native version also

ims7inc commented 1 year ago

⚠️ Unsupported Version of React Native ℹ️ It looks like your issue or the example you provided uses an unsupported version of React Native. Due to the number of issues we receive, we're currently only accepting new issues against one of the supported versions. Please upgrade to latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If you cannot upgrade, please open your issue on StackOverflow to get further community support.

tried in Latest React Native version also

ims7inc commented 1 year ago

My requirement is like, When App will goes to background i want to hide the Screen content and when the app will comes to foreground i want to show the content by setting and clearing FLAG_SECURE. but focus is changing when Modal/Alert components render in screen

@Override onWindowFocusChanged method is triggering when Modal component triggers

I tried with onPause() and onResume() also but onPause method is triggering with delay so screen content is not hidden when App goes background

ChiBao284 commented 1 year ago

Same issue

sorrelsjack commented 1 year ago

I have the same issue, as well as the same use case. I did do some deep diving into the Android code, and from my understanding, this seems to be caused by the fact that the React Native Modal component is based off the Android Dialog class: https://github.com/facebook/react-native/blob/714b502b0c7a5f897432dbad388c02d3b75b4689/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ModalHostShadowNode.java

I'm going to keep looking to see if I can figure out a workaround or something.

BishoSBA commented 1 year ago

Was any solution found for this issue? I am facing it currently as well

mdcuk34 commented 1 year ago

Facing the same issue as well :( - did anyone find a work around?

samstoppani-tred commented 1 year ago

Same thing is happening for me too :(

andydotdaniel commented 10 months ago

In case people still need help on this. I had the same exact requirements as @ims7inc and found a workaround.

The workaround involved building my own Android native module, and showing a native Android dialog, with the following steps:

  1. I detected two events: "home" and "recent apps" button presses which put the app in background. The answer in this StackOverflow thread shows a good way of doing that.
  2. Create a custom class that extends from the Android Dialog class. Set this class up so your dialog takes up the full screen and is just a solid background or whatever you want to hide the screen content. Override the onWindowFocusChanged method in this class to close the dialog when focus is changed to true.
  3. Use the button press callbacks from step 1 to add the FLAG_SECURE flag for when "home" is pressed, and to show the dialog from step 2 when "recent apps" button is pressed (so that it overlays any other existing modals). If you're developing for <= Android 11 (Red Velvet Cake and below), then add FLAG_SECURE instead of the dialog.
  4. Clear the FLAG_SECURE flag using onResume().
  5. The dialog will close itself after you come back to foreground from "recents screen" because the implemented onWindowFocusChanged() will be called, and onResume() is always called when coming back from home (but not necessarily when from recents which is why we need these two different implementations).

If you're wondering why we don't just show the dialog when pressing "home" instead of using FLAG_SECURE, the reason is because there's a delay and the dialog is not shown in time before the app dismisses when pressing home.

If you're wondering why we don't just use FLAG_SECURE for everything, it's because in >= Android 12 (Snow Cone), when pressing the "recents apps" button, I realized that the app isn't actually going in to the background yet (onPause() is not called), so whatever is using the FLAG_SECURE flag won't be called yet. Behavior is different for <= Android 11.

Trying to do this through React led me to nowhere. This was the best approach I could come up with. Hope it helps!

ys-sherzad commented 8 months ago

Any proper solution for this?

ys-sherzad commented 8 months ago

@andydotdaniel Mind if I ask to share your solution

3KINGZ commented 5 months ago

any work around to this @andydotdaniel @ys-sherzad

douglasjunior commented 5 months ago

On Android, the background state means that the React Native Activity is in background, and not necessary the entire app.

To handle this, I created a package that implements the Android Lifecycle API for React Native: https://github.com/douglasjunior/react-native-applifecycle

Why Use This?

The original AppState API provided by React Native behaves differently between Android and iOS, particularly regarding the background state:

  • On iOS, the background state signifies that the entire app is in the background.
  • On Android, the background state indicates that the React Native Activity is in the background, which might not necessarily mean the entire app is in the background.

By using react-native-applifecycle, you can handle these differences seamlessly across both platforms, ensuring that the state background will be dispatched only when the entire app is in background.

samstoppani-tred commented 4 months ago

@douglasjunior... you're a legend! 🙌

hikaaam commented 2 months ago

could this triggering the blur appstate ?

image

image