Search code examples
androidandroid-themeandroid-10.0

Listening on "Dark Theme" in notification area toggle and be notified of a change


I can get UI_MODE_NIGHT_MASK by calling resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK.

I need to listen to this variable and change my theme on receiving new value.

I think I could add a BroadcastReceiver so I can do a getSystemService(A_CONSTANT_FROM_Context) and registering a theme callback similar to ConnectivityManager.NetworkCallback. But I only found these in docs: extending Theme.MaterialComponents.DayNight on my theme styles and having values-night. Question dark them config which already has an accepted answer refers to this documentation.


Solution

  • To get informed about the uiMode change add configChanges attribute in your AndroidManifest.xml:

    <application
        ...>
        <activity
            android:name=".YourActivity"
            ...
            android:configChanges="uiMode"/>
    </application>
    

    And then in you activity listen for the config change:

    public class YourActivity extends AppCompatActivity {
    
        protected Configuration mPrevConfig;
    
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ...
            mPrevConfig = new Configuration(getResources().getConfiguration());
        }
    
        @Override
        public void onConfigurationChanged(@NonNull Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            configurationChanged(newConfig);
            mPrevConfig = new Configuration(newConfig);
        }
    
        protected void configurationChanged(Configuration newConfig) {
            if (isNightConfigChanged(newConfig)) { // night mode has changed
                recreate();
                // do your thing
            }
        }
    
        protected boolean isNightConfigChanged(Configuration newConfig) {
            return (newConfig.diff(mPrevConfig) & ActivityInfo.CONFIG_UI_MODE) != 0 && isOnDarkMode(newConfig) != isOnDarkMode(mPrevConfig);
        }
        public static boolean isOnDarkMode(Configuration configuration) {
            return (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
        }
    }