4

I'm having a big issue managing dark mode manually.

How does the app work

On application startup the first activity checks in SharedPreferences if the user chose to enable dark mode or to stay in light mode (default), then it changes it accordingly to the user preference:

Edit: as CSmith requested here's when the theme selector gets called in the activity

//FirstActivity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppThemeSelector.checkAndShowTheme(getApplicationContext());
...

And here's the theme selector method

//AppThemeSelector.class
    public static void checkAndShowTheme(Context context){
        SharedPreferences sharedPreferences = context.getSharedPreferences(
                PreferencesValues.SHARED_DARKMODE_MAP, Context.MODE_PRIVATE
        );

        boolean darkMode = sharedPreferences.getBoolean(PreferencesValues.SHARED_DARKMODE_ENABLED, false);

        if(darkMode){
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        }else{
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }
    }

So far so good, whenever it starts it sets its theme with the one chosen by the user and everything is working fine.

Where does the issue happen

Apparently the issue seems to happen only on my Xiaomi Mi A2 Lite (Android 10) because I've tested on a Pixel 2 (Android 11) and on the emulator (Android 10) and when the app is resumed from the recent apps everything works normal.

The issue

A consistent way of reproducing my issue is: suppose I have my application on manual light mode set and my system is in dark mode. I open the application (either staying in home activity or going to another activity causes the same issue) then I go into system settings and change system language.

When I reopen the app from the recent apps tab it looks like the app tries to restart but it crashes mid way (not sure about that because logcat shows nothing regarding crashes nor the app displays any dialog about crashing) and when it starts it automatically sets its theme to the system theme (so in my example case it goes to dark mode).

The problem at this point is that some texts that are meant to be seen in dark mode now have light mode theming making them blend with the black background; the switch that is used in app to change from dark to light mode stays on the correct settings (showing that dark mode is not enabled) but the app is in dark mode. If the app is restarted it everything goes back to normal and the app is correctly showing in light theme.

I haven't been able to reproduce the problem when the app stays in the background for a long time, but I think it could happen as well.

halfer
  • 19,824
  • 17
  • 99
  • 186
x-devel
  • 148
  • 2
  • 11
  • 1
    can you show where in your startup activity you're checking `SharedPreferences` and calling the `setDefaultNightMode` API? – CSmith Jun 03 '21 at 18:42
  • Sure! I just updated the main post @CSmith – x-devel Jun 03 '21 at 20:38
  • 1
    please try moving the `checkAndShowTheme()` call to an `Application` class override and its `onCreate()` method (see https://stackoverflow.com/questions/12834379/extending-android-application-class)? Also add some logging to `checkAndShowTheme()` to show when its being called and confirming the value read from `SharedPreferences` – CSmith Jun 04 '21 at 11:52
  • I already had an Application class that managed the database and your logic is sound. Logging the values of the `checkAndShowTheme()` method after putting the check in the Application class always logs the correct values and the problem seems solved. I'm not 100% sure the issue is gone because yesterday after rebooting my phone and before changing the code I wasn't getting the issue anymore. Anyways, at the moment with your solution the problem isn't there so I would like to mark your answer as accepted. So if that's ok for you make a post and I'll mark it. Thank you for your time @CSmith – x-devel Jun 06 '21 at 08:43

3 Answers3

5

use

android:configChanges="uiMode" 

in manifest activity tag like this :

<activity
android:name=".MyActivity"
android:configChanges="uiMode" />
Ali Najafi
  • 118
  • 1
  • 3
  • LIFE SAVER! I tried anything and nothing helped. My Radio App kept restarting on night mode change. This was the only thing that solved it. – Anticro Jun 21 '22 at 07:50
2

AppCompatDelegate.setDefaultNightMode() can cause activities to be re-created, I usually perform this check once and do so in an Application class override.

Please try moving your call to checkAndShowTheme() to the onCreate method of an Application class override

public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();
        AppThemeSelector.checkAndShowTheme(getApplicationContext());
    }
}

this way the setDefaultNightMode() is called once and very early in an applications lifecycle.

To be honest I'm not certain why the Xiaomi Mi A2 showed different behavior, I'm merely suggesting a practice that I've followed with success, and hope that it helps you.

CSmith
  • 13,318
  • 3
  • 39
  • 42
1

I think your issue is most probably because of the forced dark mode in Andriod Q and above. MIUI has implemented it in some weird way that it converts every app in dark mode. You should use this in your light theme style file

<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
Praveen
  • 3,186
  • 2
  • 8
  • 23
  • My Mi A2 Lite doesn't use MIUI but I've tried your fix anyway and unfortunately it doesn't seem to do anything – x-devel Jun 03 '21 at 18:30