Mackalester
Mackalester

Reputation: 164

Android: Detect if night mode is set to FOLLOW_SYSTEM with AppCompatDelegate

I'm trying to make a settings option that allows the user to choose whether the app should be in night mode, day mode or follow the system default. In order to display the current setting to the user I need to get it from the system. However the code I'm using below always returns MODE_NIGHT_UNSPECIFIED. Am I doing something wrong here?

I have the following code:

val x = AppCompatDelegate.getDefaultNightMode()
        when (x) {
            AppCompatDelegate.MODE_NIGHT_NO -> {"testsadflke-  MODE_NIGHT_NO".log()}
            AppCompatDelegate.MODE_NIGHT_YES -> {"testsadflke-  MODE_NIGHT_YES".log()}
            AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> {"testsadflke-  MODE_NIGHT_AUTO_BATTERY".log()}
            AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> {"testsadflke-  MODE_NIGHT_FOLLOW_SYSTEM".log()}
            AppCompatDelegate.MODE_NIGHT_UNSPECIFIED -> {"testsadflke-  MODE_NIGHT_UNSPECIFIED".log()}
        }

The log output is:

2020-07-01 21:47:08.751 6783-6783/com.example.macrotracker D/(AnyExt.kt:6)log(): Object: testsadflke-  MODE_NIGHT_UNSPECIFIED

However I think this is incorrect because my appTheme extends the material DayNight theme. Additionally, when I enable or disable night mode, my app changes theme, so it must be following the system mode. Any help would be much appreciated!

Upvotes: 2

Views: 2283

Answers (1)

ianhanniballake
ianhanniballake

Reputation: 199805

AppCompat's night mode support comes at two layers:

  • the "default" layer - controlled by setDefaultNightMode(), read via getDefaultNightMode()
  • the "local" layer - controlled by setLocalNightMode(), read via getLocalNightMode()

The "default" layer only applies if you have not set a local mode (i.e., getLocalNightMode() returns MODE_NIGHT_UNSPECIFIED) by explicitly calling setLocalNightMode() with a different value.

For a similar reason, if you've never called setDefaultNightMode(), then getDefaultNightMode() is expected to return MODE_NIGHT_UNSPECIFIED - unspecified means that you haven't set it to any particular value.

It is important to note that AppCompatDelegate does not persist any value you set - you need to call setDefaultNightMode() every time your application is created (i.e., to restore whatever value you want / have previous saved yourself after process death) and setLocalNightMode() (if you use that on a particular Activity/Dialog) when that component is created.

As per the MODE_NIGHT_UNSPECIFIED documentation:

If both the default and local night modes are set to this value [MODE_NIGHT_UNSPECIFIED], then the default value of MODE_NIGHT_FOLLOW_SYSTEM is applied.

Therefore if you're not using the local mode at all, then you can treat MODE_NIGHT_UNSPECIFIED the same as MODE_NIGHT_FOLLOW_SYSTEM as that is exactly what AppCompat does in the case where both are MODE_NIGHT_UNSPECIFIED.

Upvotes: 3

Related Questions