androidandroid-themeandroid-dark-themeandroid-darkmode

Android manual dark mode on app resume/restart causes app theme to not work correctly


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.


Solution

  • 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.