6

AppCompatDelegate.MODE_NIGHT_AUTO is not updating my existing activity and I'm not sure why.

I dynamically allow the user to change night mode. If the user changes the mode to auto I set the default night mode then recreate the activity:

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
recreate();

If I change to MODE_NIGHT_YES or MODE_NIGHT_NO, it works as expected. If I change to MODE_NIGHT_AUTO, it goes to the correct dark/light theme, but then it fails to update the activity after the transition from day to night. It kind of sucks to test this because I have to wait for sunrise/sunset (EDIT: apparently I can manually change the time on the device rather than having to wait...so long as the location permission is not used).

Do I have to do a manual check for the night mode flag in onresume and manually update resources for existing activities, or am I doing something wrong? If I rotate the device and the activity is recreated after sunset then the dark theme is correctly picked up, but before rotation it will still be showing the light theme.

Support lib 23.4.0, Android version 6.0.

timothyjc
  • 2,188
  • 3
  • 29
  • 54
  • It might be argued it's a bug. It is not unreasonable to expect that the switch from day to night (or the other way) should trigger a configuration change that would automatically recreate your activities. At the very least it would be nice to opt into that. I guess it's worth reporting in AOSP bug tracker. – Marcin Koziński Jun 04 '16 at 15:22

2 Answers2

4

In case anyone else wants to know what I did to solve this (not sure if it is the right way to do it though):

private int mCurrentNightMode;

@Override
protected void onCreate(Bundle savedInstanceState) {
   mCurrentNightMode = getCurrentNightMode();
}

@Override
protected void onPostResume() {
    super.onPostResume();

    if (hasNightModeChanged()) {
        delayedRecreate();
    }

}

private void delayedRecreate() {
    Handler handler = new Handler();
    handler.postDelayed(this::recreate, 1);
}

private boolean hasNightModeChanged() {
    getDelegate().applyDayNight();
    return mCurrentNightMode != getCurrentNightMode();
}

private int getCurrentNightMode() {
    return getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
}
timothyjc
  • 2,188
  • 3
  • 29
  • 54
2

It's been fixed in AppCompat 24.2.0. Revision history lists this as a "behaviour change" for 24.2.0:

If you use the appcompat library's day/night functionality, the system now automatically recreates your activity whenever the day/night mode changes (either because of the time of day, or because of a call to AppCompatDelegate.setLocalNightMode()).

Marcin Koziński
  • 10,835
  • 3
  • 47
  • 61
  • Cheers! I noticed that too :) – timothyjc Aug 18 '16 at 13:35
  • 1
    This works for for the current Activity. However, when going back on the activities it doesn't recreate anything. If you have something like a ViewPager creating new Fragments you'll suddenly get a mix of day and night. https://stackoverflow.com/a/37631109/467650 solved this for me. – Roy Solberg Jul 05 '17 at 06:15
  • 1
    @RoySolberg I can confirm that this issue is still present in `androidx 1.0.0`. – l33t Nov 19 '18 at 18:05