cordova-android
cordova-android copied to clipboard
Status bar background color overridden by the splash screen animation on Android 13
Bug Report
Problem
On Android 13 the status bar background color is always black. I've set the color on the config.xml with the StatusBarBackgroundColor preference and it works on ios and android < 13 but not on Android 13.
What is expected to happen?
Status bar should have the color set in the config.xml.
What does actually happen?
Status bar color is black. It shows the correct color for a few milliseconds than it becomes black.
Information
Just set the background color with StatusBarBackgroundColor in the config.xml and run the application on Android 13.
Command or Code
<preference name="StatusBarBackgroundColor" value="#cccccc" /> in config.xml
This issue is solved removing the splash screen animation from the splash screen plugin:
so the splash screen plugin should fix this part of the code.
Environment, Platform, Device
Android 13, Android studio 2021.2.1 patch 2
Version information
cordova cli v 11.0.0 cordova-android v 11.0.0 cordova-plugin-statusbar v3.0.0
Checklist
- [x] I searched for existing GitHub issues
- [x] I updated all Cordova tooling to most recent version
- [x] I included all the necessary information above
Moving this to the cordova-android repo as that is what contains the splashscreen code.
More investigation is needed.
The code you commented out is for supporting the new Android 12 Splash Screen API, which has been proven to work on Android <= 12L.
As you said, the issue appears in Android 13+. There is a possibility that Google has introduced a change that broke this and the issue is on Google's end, and not Cordova.
Maybe Google introduced a new process for setting the status bar color, in Android 13, only if the Android 12 Splash Screen API compatibility library is used?
But nothing seems apparent in the Android 13 release notes regarding such a change.
More investigation is needed.
The code you commented out is for supporting the new Android 12 Splash Screen API, which has been proven to work on Android <= 12L.
As you said, the issue appears in Android 13+. There is a possibility that Google has introduced a change that broke this and the issue is on Google's end, and not Cordova.
Maybe Google introduced a new process for setting the status bar color, in Android 13, only if the Android 12 Splash Screen API compatibility library is used?
But nothing seems apparent in the Android 13 release notes regarding such a change.
Yeah that was only a quick test I did but removing that part was solving the issue. I suppose there must be something in there that causes the bug. I've tried playing with the methods for the animation but it seems that's the whole animation that's causing the issue.
Here was one thing I noticed
Following your previous steps:
- Set the color in
config.xmlas you previously mentioned:
<preference name="StatusBarBackgroundColor" value="#cccccc" />
- Launch the App
- Notice the Black Status Bar
- Minimize the App, place in background (Do not close)
- Open "Settings → Wallpaper & style"
- Change your color by selecting something under Wallpaper colors or Basic colors.
- Return to the app (bring to foreground)
- Notice that the status bar is now the color your defined.
This is one of the reasons why I am wondering if it is an Android bug and not Cordova. It seems kind of unusualy why changing the system settings will make changes to the app display. And yet its not anytrhing related to the color you picked in the settings. Its kind of confusing why this is happening, but once you close and reopen the app it same issue appears.
I can replicate this, @erisu, and would just add that between 7. and 8. my app does a sort of restart. Any window I had opened within my app is closed upon returning to the app.
Also, it is not just the color of the status bar. I am using StatusBar.overlaysWebView(true); and that also doesn't get applied unless I do @erisu's "fix".
@erisu my previous comment that the "app does a sort of restart" might actually be quite relevant when you look at this issue: https://github.com/apache/cordova-plugin-statusbar/issues/234
There, the author states that using window.location.replace('/home'); (= also a sort of restart of the app) solves their StatusBarOverlaysWebView problem (the problem being that safe areas from notch/status bar are not being set/read).
So I think that is the answer why your steps work to "solve" the issue (...until the next "proper" app restart).
The key here seems to be the postSplashScreenTheme as very loosely documented by Android: https://developer.android.com/reference/kotlin/androidx/core/splashscreen/SplashScreen. This feature is supported by the splashscreen behaviour in cordova-android core: https://github.com/apache/cordova-android/pull/1441
With Android 12+, this theme doesn't apply until the splash screen is fully hidden, and when it does apply it will clobber any settings configured by the Statusbar plugin while the splash was displayed.
In my case, I've added a styles.xml file with the configuration my app was setting Statusbar to, and this resolved the issue.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/windowBackground</item>
<item name="android:statusBarColor">@android:color/white</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>
Added to the config.xml like this:
<widget ...>
<platform name="android">
<preference name="AndroidPostSplashScreenTheme" value="@style/AppTheme" />
<resource-file src="res/android/styles.xml" target="app/src/main/res/values/styles.xml" />
</platform>
</widget>
It's not entirely clear that this can be fixed, given the root issue is that Android itself applies the theme at it's own discretion. If the post splash theme is significantly different from the Statusbar configuration, any attempted fix will likely result in the status bar flickering through the wrong state before showing the desired state.
Given this behaviour, I feel that the best solution in practice is to recommend developers create a customised post-splash style, and reduce their dependency on the Statusbar plugin for Android for setting the initial static styles.
Oh... another sharp edge... launching the app on to a phone directly from Android studio will bypass the normal Splashscreen behaviours! This confused me for quite a while as it seemed like no changes I made really applied.
To test whether the post-splash theme is properly applying, you will need to close the app and relaunching via the phone, NOT via Android Studio.
The key here seems to be the
postSplashScreenThemeas very loosely documented by Android: https://developer.android.com/reference/kotlin/androidx/core/splashscreen/SplashScreen. This feature is supported by the splashscreen behaviour incordova-androidcore: #1441With Android 12+, this theme doesn't apply until the splash screen is fully hidden, and when it does apply it will clobber any settings configured by the Statusbar plugin while the splash was displayed.
In my case, I've added a
styles.xmlfile with the configuration my app was setting Statusbar to, and this resolved the issue.<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/windowBackground</item> <item name="android:statusBarColor">@android:color/white</item> <item name="android:windowLightStatusBar">true</item> </style> </resources>Added to the
config.xmllike this:<widget ...> <platform name="android"> <preference name="AndroidPostSplashScreenTheme" value="@style/AppTheme" /> <resource-file src="res/android/styles.xml" target="app/src/main/res/values/styles.xml" /> </platform> </widget>
Thanks a lot for your solution, it helped me and it worked. I just changed 2 things:
- I removed
<item name="android:windowBackground">@color/windowBackground</item>because that line made the build failed - I change the color from @android:color/white to @android:color/transparent so I am still able to change color below the status bar (I use
overlaysWebView(true)), so that it works in every condition, including dark mode
The key here seems to be the
postSplashScreenThemeas very loosely documented by Android: https://developer.android.com/reference/kotlin/androidx/core/splashscreen/SplashScreen. This feature is supported by the splashscreen behaviour incordova-androidcore: #1441With Android 12+, this theme doesn't apply until the splash screen is fully hidden, and when it does apply it will clobber any settings configured by the Statusbar plugin while the splash was displayed.
In my case, I've added a
styles.xmlfile with the configuration my app was setting Statusbar to, and this resolved the issue.<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/windowBackground</item> <item name="android:statusBarColor">@android:color/white</item> <item name="android:windowLightStatusBar">true</item> </style> </resources>Added to the
config.xmllike this:<widget ...> <platform name="android"> <preference name="AndroidPostSplashScreenTheme" value="@style/AppTheme" /> <resource-file src="res/android/styles.xml" target="app/src/main/res/values/styles.xml" /> </platform> </widget>
I wonder if we can extend the splashscreen theme so that we can set the statusbar stuff like <item name="android:windowLightStatusBar">true</item> in addition to having the same statusbar config in our post theme.
I've added this to a 12.0.1 for now...
But I think the solution might be to create a Cordova Theme and have the statusbar preferences manipulate the statusbar theme values respectively. The post theme can default to this new cordova theme. If that's the route we take, then that may be considered a breaking change... in which case we'd want to change the milestone to 13.x.
FWIW I've ran into this issue on my own apps and https://github.com/apache/cordova-android/issues/1501#issuecomment-1294202691 served as a workaround for the time being.
I created a theme xml file that looks like this (style name can be changed if desired):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.App.TotalPave" parent="Theme.AppCompat.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
and inside my config xml:
<preference name="StatusBarOverlaysWebView" value="true" />
<preference name="AndroidPostSplashScreenTheme" value="@style/Theme.App.TotalPave" />
<platform name="android">
<content src="index.html" />
<resource-file src="./res/android/values/TotalPaveTheme.xml" target="app/src/main/res/values/TotalPaveTheme.xml" />
...
Without the workaround, after app launch, the splashscreen will turn black, while maintaining the overlay state. This workaround allowed me to keep the colour transparent as one would expect for an overlay state. If you use the statusbar differently, then the theme config may need to be adjusted to fit your needs.
I think setting FadeSplashScreen to false should fix the issue, the problem seems related to the splash animation and since the setting will remove the animation it should not cause the issue.
Can you try the setting and/or provide a sample app that reproduces the issue?