facebook / react-native

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

StatusBar Area Turns Black When Hidden Instead of Inheriting Background Color #46070

Closed softgenicsShubham closed 2 months ago

softgenicsShubham commented 2 months ago

Description

When hiding the StatusBar using StatusBar hidden, the area where the StatusBar was turns black instead of inheriting the background color of the parent View.

Steps to reproduce

  1. Create a new React Native app.
  2. Hide the StatusBar using <StatusBar hidden />.
  3. Observe that the StatusBar area turns black. WhatsApp Image 2024-08-15 at 12 43 43

React Native Version

0.75.1

Affected Platforms

Runtime - Android

Output of npx react-native info

System:
  OS: macOS 14.6.1
  CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Memory: 345.66 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.5.1
    path: /usr/local/bin/node
  Yarn:
    version: 3.6.4
    path: /usr/local/bin/yarn
  npm:
    version: 10.8.2
    path: /usr/local/bin/npm
  Watchman:
    version: 2024.07.15.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /Users/apple/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.18034.62.2411.12169540
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.11
    path: /usr/bin/javac
  Ruby:
    version: 3.0.0
    path: /Users/apple/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.1
    wanted: 0.75.1
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

wu1s0sJhIXF823pi3g==/split_config.arm64_v8a.apk!/lib/arm64-v8a:/data/app/~~l0IulceH14dbm2z6KPDTow==/com.linkedin.android-K2drwu1s0sJhIXF823pi3g==/split_config.en.apk!/lib/arm64-v8a:/data/app/~~l0IulceH14dbm2z6KPDTow==/com.linkedin.android-K2drwu1s0sJhIXF823pi3g==
08-16 22:10:25.061 17150 17150 V GraphicsEnvironment: ANGLE Developer option for 'com.linkedin.android' set to: 'default'
08-16 22:10:25.061 17150 17150 V GraphicsEnvironment: Neither updatable production driver nor prerelease driver is supported.
08-16 22:10:25.065 17150 17150 D NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: false
08-16 22:10:25.069 17150 17150 D NetworkSecurityConfig: Using Network Security Config from resource network_security_config debugBuild: false
08-16 22:10:25.260 17150 17150 I EKGCrashLoopDetector: Last crash time: 0
08-16 22:10:25.261 17150 17150 D EKGCrashLoopDetector: Didn't crash at startup last launch
08-16 22:10:25.329 17150 17177 D ExceptionHandler: [EKG-BackgroundExecutor] Uploading pending java crashes
08-16 22:10:25.334 17150 17177 D ExceptionHandler: [EKG-BackgroundExecutor] Number of crash files to process: 0
08-16 22:10:25.356 17150 17150 D EKGNDKCrashReporter: miniDumpFilePath: /data/user/0/com.linkedin.android/files/ekg_ndk_crashes_v1/1.47.57/4fa0fd59-6b98-4ad2-c0f956b0-ad8464a7.dmp
08-16 22:10:25.357 17150 17150 D EKGNDKCrashReporter: metadataFilePath: /data/user/0/com.linkedin.android/files/ekg_ndk_crashes_v1/1.47.57/4fa0fd59-6b98-4ad2-c0f956b0-ad8464a7.metadata
08-16 22:10:25.360 17150 17177 D ExceptionHandler: [EKG-BackgroundExecutor] Uploading native crashes
08-16 22:10:25.361 17150 17177 D ExceptionHandler: [EKG-BackgroundExecutor] Number of crash files to process: 0
08-16 22:10:25.362 17150 17150 D CrashReporter: [main] logBreadcrumb: app_launch
08-16 22:10:25.377 17150 17150 I FlagshipApplication: [main] Granular phase APP_ATTACH with pillar PAI completed.
08-16 22:10:25.381 17150 17150 I FlagshipApplication: [main] Granular phase APP_ATTACH completed. Interval(startNanos=1723826425166000000ns, durationNanos=212000000ns)
08-16 22:10:25.444 17150 17150 I FirebaseApp: Device unlocked: initializing all Firebase APIs for app [DEFAULT]
08-16 22:10:25.464 17150 17150 I FirebaseInitProvider: FirebaseApp initialization successful
08-16 22:10:25.509 17150 17150 W libc    : Access denied finding property "ro.vendor.perf.scroll_opt.heavy_app"
08-16 22:10:25.523 17150 17150 E FlagshipApplication: [main] FlagshipApplication#onCreate() called for process id 17150
08-16 22:10:25.685 17150 17150 I FlagshipApplication: [main] Granular phase APP_DEPENDENCY_INJECTION completed. Interval(startNanos=1723826425536000000ns, durationNanos=149000000ns)
08-16 22:10:25.761 17150 17150 D WM-PackageManagerHelper: Skipping component enablement for androidx.work.impl.background.systemjob.SystemJobService
08-16 22:10:25.762 17150 17150 D WM-Schedulers: Created SystemJobScheduler and enabled SystemJobService
08-16 22:10:25.822 17150 17192 D CompatibilityChangeReporter: Compat change id reported: 160794467; UID 10355; state: ENABLED
08-16 22:10:25.847 17150 17191 I cr_CronetLibraryLoader: Cronet version: 102.0.5005.125, arch: aarch64
08-16 22:10:25.916 17150 17150 W DaggerInfraApplicationD: [main] Cannot set the application tracking stack multiple times. Skipping assignment.
08-16 22:10:25.916 17150 17150 D GlobalSequence: Global Sequence already initialized. Ignoring
08-16 22:10:25.944 17150 17215 W ThreadPoolExecutor: [ConnectionMonitor-1] ConnectionStateChangedListener added to ConnectionMonitor, but ConnectionMonitor has not been started.
08-16 22:10:25.951 17150 17150 D LixManagerImpl: [main] Triggering sync for lix lixType 0
08-16 22:10:25.952 17150 17150 D LixNetworkManager: [main] Batch Fetch Lix url:/lix/lixFrontendTreatmentsV2?action=batchGet
08-16 22:10:25.989 17150 17150 D AppLaunchRateLimiter: [main] shouldLimitAppLaunchNetworkCalls: S600
08-16 22:10:25.989 17150 17150 D InfraAppLaunchOnAppProc: [main] onAppProcessStarted(): shouldLimitNetworkCalls=false
08-16 22:10:26.385 17150 17150 D EventBus: No subscribers registered for event class com.linkedin.android.infra.events.VideoAutoPlaySettingChangedEvent
08-16 22:10:26.386 17150 17150 D EventBus: No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent
08-16 22:10:26.441 17150 17150 I Choreographer: Skipped 55 frames!  The application may be doing too much work on its main thread.
08-16 22:10:26.832 17150 17234 I WM-WorkerWrapper: Worker result SUCCESS for Work [ id=18d6f5b6-467e-4055-94ef-d45d55d69a7d, tags={ com.linkedin.android.litrackinglib.network.SendTrackingEventWorker, period_sync_work } ]
08-16 22:10:26.871 17150 17208 I LMDBLRUCache: Entry init duration: 957ms
08-16 22:10:26.900 17150 17236 I WM-WorkerWrapper: Worker result SUCCESS for Work [ id=715a731f-b8bc-4b8f-acde-b5c83c9e3ff4, tags={ com.linkedin.android.segment.ChameleonPeriodicWork } ]
08-16 22:10:27.342 17150 17234 I WM-WorkerWrapper: Worker result SUCCESS for Work [ id=e10f1dce-8389-4084-a7ae-dc4efa900ecb, tags={ com.linkedin.android.litrackinglib.network.SendTrackingEventWorker, send_one_batch_events_work } 
0

Reproducer

https://github.com/softgenicsShubham/react-native-issues.git

Screenshots and Videos

No response

shubhamguptadream11 commented 2 months ago

@softgenicsShubham Is this happening on iOS as well?

softgenicsShubham commented 2 months ago

No

shubhamguptadream11 commented 2 months ago

Screenshot_20240817_094949 @softgenicsShubham I tried with reproducer you provided. Its not happening at my end. I am using Pixel 7 Pro API 33 as an emulator to run it. Can anyone else check this?

softgenicsShubham commented 2 months ago

@shubhamguptadream11, you are right, but this will only happen on physical devices. On the emulator, it works fine on my side as well.

shubhamguptadream11 commented 2 months ago

@softgenicsShubham Let me try on physical device.

shubhamguptadream11 commented 2 months ago

@softgenicsShubham You are right. On physical device it is reproducible. One work around you can try is <StatusBar backgroundColor={'transparent'} translucent/>.

softgenicsShubham commented 2 months ago

@shubhamguptadream11 that's correct, but i want to keep it hidden.

shubhamguptadream11 commented 2 months ago

It seems that API's used here in setHidden function is deprecated now. https://github.com/facebook/react-native/blob/3e6b4fa23088e92fb41608fa7dbe3cf410626fb3/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt#L134

May be we need to try out this new APIs: https://developer.android.com/training/system-ui/status But strange thing is How it's working in emulator though 🤔 .

shubhamguptadream11 commented 2 months ago

https://github.com/facebook/react-native/issues/39362 https://github.com/expo/expo/issues/15244 It seems to be widely known issue.

I tried with sample android app(Without react native), there also it's not working. I tried new flags as well. Nothing works as of now.

shubhamguptadream11 commented 2 months ago

After debugging this, I found a way to solve this issue. setHidden function is responsible for toggling view of status bar. https://github.com/facebook/react-native/blob/25d6a152cc720e0d5f860dab228ac2e43321d9e4/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.kt#L122

What real issue is? For android devices with camera area on top a black strip is coming after hidding status bar.

Previous Implementation:

  override fun setHidden(hidden: Boolean) {
    val activity = currentActivity
    if (activity == null) {
      FLog.w(
          ReactConstants.TAG,
          "StatusBarModule: Ignored status bar change, current activity is null.")
      return
    }
    UiThreadUtil.runOnUiThread(
        Runnable {
          val window = activity.window ?: return@Runnable
          if (hidden) {
            window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
          } else {
            window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
            window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
          }
        })
  }

It seems that FLAG_FULLSCREEN flag are not enough to draw content in camera area.

Solution: In order to tackle this android exposes 2 flags:

By adding this flag we are now able to hide status bar properly.

  override fun setHidden(hidden: Boolean) {
    val activity = currentActivity
    if (activity == null) {
      FLog.w(
          ReactConstants.TAG,
          "StatusBarModule: Ignored status bar change, current activity is null.")
      return
    }
    UiThreadUtil.runOnUiThread(
        Runnable {
          val window = activity.window ?: return@Runnable
          if (hidden) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
              // Ensure the content extends into the cutout area
              window.attributes.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
              window.setDecorFitsSystemWindows(false)
            }
            window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
          } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
              window.attributes.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
              window.setDecorFitsSystemWindows(true)
            }
            window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
            window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
          }
        })
  }

@softgenicsShubham Please try by replacing setHidden function with this new one. Test it either by using a patch or build from source. Let me know whether it is fixing it or not?

Note: This will work above Android 11 and above

shubhamguptadream11 commented 2 months ago

Device Detail: Oneplus9 5G OS 11 Before fix: https://github.com/user-attachments/assets/589098ff-a3fa-4962-a15b-ceacbfd03d2d

After fix: https://github.com/user-attachments/assets/a87dd8e4-3624-4e09-99da-a14f9e19fcc6

softgenicsShubham commented 2 months ago

@shubhamguptadream11 The fix is working well. Thanks for the help!

shubhamguptadream11 commented 2 months ago

@softgenicsShubham Thanks for testing it out. I am raising a PR then.

shubhamguptadream11 commented 2 months ago

@softgenicsShubham We can close this issue after merging the PR in main repo. Currently you are using it as patch right?

softgenicsShubham commented 2 months ago

Apologies for the confusion, I’ve reopened the issue. Yes, I’m currently using it as a patch. I’ll wait for the PR to be merged into the main repo before officially closing the issue. Thanks for the clarification @shubhamguptadream11 !

shubhamguptadream11 commented 2 months ago

Fixed PR is merged now.