javaandroidapplication-settingsandroid-night-mode

How can I save the state of the night mode in my android app?


I have a settings-activity in my app, where the user can choose between light mode, dark mode, and follow the system with three radio buttons. But when the app restarts, follow the system is always applied regardless of what is selected on the radio buttons. I tried it with SharedPreferences but it didn't work. How can I fix this?

Java class:

package com.example.formelrechner;

import...

public class Einstellungen extends AppCompatActivity {

    RadioGroup radioGroup;
    RadioButton radioButton, radioButton2, radioButton3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        if (AppCompatDelegate.getDefaultNightMode()==AppCompatDelegate.MO DE_NIGHT_YES) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        }

        if (AppCompatDelegate.getDefaultNightMode()==AppCompatDelegate.MODE_NIGHT_NO) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_einstellungen);


        radioGroup = findViewById(R.id.radiogroup);
        radioButton = findViewById(R.id.radioButton);
        radioButton2 = findViewById(R.id.radioButton2);
        radioButton3 = findViewById(R.id.radioButton3);

        radioButton.setChecked(Update("SaveStateOne"));
        radioButton2.setChecked(Update("SaveStateTwo"));
        radioButton3.setChecked(Update("SaveStateThree"));



        radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean one_isChecked) {
                SaveintosharedPrefs("SaveStateOne", one_isChecked);
                if (one_isChecked) {
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

                }
            }
        });

        radioButton2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean two_isChecked) {
                SaveintosharedPrefs("SaveStateTwo", two_isChecked);
                if (two_isChecked) {
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                }
            }
        });

        radioButton3.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean three_isChecked) {
                SaveintosharedPrefs("SaveStateThree", three_isChecked);
                if (three_isChecked) {
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
                }
            }
        });

    }

    private void SaveintosharedPrefs(String key, boolean value) {

        SharedPreferences sp = getSharedPreferences("SaveState",MODE_PRIVATE);
        final SharedPreferences.Editor editor = sp.edit();

        editor.putBoolean(key,value);
        editor.apply();
    }

    private boolean Update(String key) {

        SharedPreferences sp = getSharedPreferences("SaveState",MODE_PRIVATE);
        return sp.getBoolean(key, false);
    }

}


Solution

  • I did the same thing for my application in Kotlin. But you can convert it to java, is almost the same.

    You need to create a new class for Sharing Preferences:

    class SettingsSaveData(context:Context) {
    
    private var sharedPreferences: SharedPreferences =context.getSharedPreferences("file", Context.MODE_PRIVATE)
    
    fun setDarkMode(state: Boolean){
        val editor = sharedPreferences.edit()
        editor.putBoolean("Dark", state)
        editor.apply()
    }
    
    fun loadDarkMode(): Boolean? {
        val state = sharedPreferences.getBoolean("Dark", false)
        return (state)
    }
    

    }

    In your Settings Activity, you need to have something like this:

    class SettingsActivity : AppCompatActivity() {   
       private lateinit var settingSaveData: SettingsSaveData
    
    override fun onCreate(savedInstanceState: Bundle?) {
        settingSaveData = SettingsSaveData(this)  // make sure to setTheme here
        if (settingSaveData.loadDarkMode() == true){  // before onCreate method
            setTheme(R.style.DarkTheme)
        }else{
            setTheme(R.style.AppTheme)
        }
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)
    
        if(settingSaveData.loadDarkMode() == true){
            switch_theme.isChecked = true            // switch_theme is my Switch
        }
    
        switch_theme.setOnCheckedChangeListener { _, isChecked ->
            if (isChecked) {
                settingSaveData.setDarkMode(true)
                restartApplication()
            }else{
                settingSaveData.setDarkMode(false)
                restartApplication()
        }  
    private fun restartApplication(){
        val i = Intent(applicationContext, SettingsActivity::class.java)
        startActivity(i)
        finish()
    }
    

    In all your activities you just need to declare:

    private lateinit var settingsSaveData:SettingsSaveData
    

    and setTheme in your onCreate method:

     settingsSaveData = SettingsSaveData(this)
        if (settingsSaveData.loadDarkMode() == true){
            setTheme(R.style.DarkTheme)
        }else{
            setTheme(R.style.AppTheme)
        }
        super.onCreate(savedInstanceState)
    

    I hope this will help you!