Skip to content
Advertisement

How to save dark mode state in android when the app is completely closed

I have a little problem. When I turn on dark mode in my app and then close my app completely in android, when I reopen it, it returns to light mode. I use AppCompatDelegate to do this. I have a settings fragment with a switch to turn on or off dark mode and it works well. I have a shared preferences on that fragment for the switch and it works. The only problem is that the rest of the application doesn’t stay in dark mode after being completely closed the reopened after. Is there a way I can save and then restore the dark mode when I close the reopen it?

Here’s my code for MainActivity:

package com.barzalou.lpapineau.test;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import com.barzalou.lpapineau.test.ui.CheckedChangeCallback;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

public class MainActivity extends AppCompatActivity implements CheckedChangeCallback {

    private AppBarConfiguration mAppBarConfiguration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, R.id.nav_maps)
            .setDrawerLayout(drawer)
            .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_exit) {
            finish();
            System.exit(0);
        }
        return false;
    }

    public void onCheckedChange(boolean isChecked) {
        if (isChecked) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
            Log.d("Dark Mode Switch State", "On");
        }
        else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
            Log.d("Dark Mode Switch State", "Off");
        }
    }

Here’s my code for SettingsFragment:

package com.barzalou.lpapineau.test.ui.settings;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.barzalou.lpapineau.test.R;
import com.barzalou.lpapineau.test.ui.CheckedChangeCallback;
import android.content.Context;

import static android.content.Context.MODE_PRIVATE;

public class SettingsFragment extends Fragment {

    private SettingsViewModel settingsViewModel;
    private static Switch DarkMode;
    private boolean SwitchOnOff;
    private CheckedChangeCallback callback = null;

    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        settingsViewModel = ViewModelProviders.of(this).get(SettingsViewModel.class);
        View root = inflater.inflate(R.layout.fragment_settings, container, false);
        final TextView textView = root.findViewById(R.id.text_settings);
        settingsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                textView.setText(s);
            }
        });
        return root;
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        DarkMode = (Switch) getView().findViewById(R.id.DarkModeSwitch);

        DarkMode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                callback.onCheckedChange(isChecked);
            }
        });
    }

    public void onAttach(final Activity activity) {
        super.onAttach(activity);
        if (activity instanceof CheckedChangeCallback) {
            this.callback = (CheckedChangeCallback) activity;
        }
    }

    public void onDetach() {
        super.onDetach();
        callback = null;
    }

    //Save and Restore Switch, Buttons, Textboxs, etc -----------------------
    @Override
    public void onStop() {
        super.onStop();
        try {
            saveData();
            Log.d("Data Save", "Data was saved");
        } catch (Exception e) {
            Log.d("Data Save", "Data could not be saved");
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        try {
            loadData();
            updateViews();
            Log.d("Data Restore", "Data was restored");
        } catch (Exception e) {
           Log.d("Data Restore", "Data was not able to get restored");
        }
    }
    //------------------------------------------------------------------------



    // Save data, load data and update views functions -----------------------
    public void saveData() {
        SharedPreferences sharedPreferences = getContext().getSharedPreferences("SharedPrefs", MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        // Add other Switches, Buttons, Texboxes, etc to save
        editor.putBoolean("SwitchState", DarkMode.isChecked());
        // Example: editor.putString("String1", textview.getText().toString());

        //---------------------------------------------------

        editor.apply();
    }

    public void loadData() {
        SharedPreferences sharedPreferences = getContext().getSharedPreferences("SharedPrefs", MODE_PRIVATE);
        SwitchOnOff = sharedPreferences.getBoolean("SwitchState", true); //Change true to false to make the switch on by default
    }

    public void updateViews() {
        DarkMode.setChecked(SwitchOnOff);
    }
    //------------------------------------------------------------------------
}

Advertisement

Answer

I found an easy and straight forward answer. I tested it multiple times to make sure. Just add the following variables in MainActivity:

int NightMode;
SharedPreferences sharedPreferences;
SharedPreferences.Editor editor;

After that, you’ll want to add the following lines in MainActivity’s OnCreate() method:

sharedPreferences = getSharedPreferences("SharedPrefs", MODE_PRIVATE);
NightMode = sharedPreferences.getInt("NightModeInt", 1);
AppCompatDelegate.setDefaultNightMode(NightMode);

And to finish it off, save all of your variables in your shared preferences using the OnSaveInstanceState method:

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);

    NightMode = AppCompatDelegate.getDefaultNightMode();

    sharedPreferences = getSharedPreferences("SharedPrefs", MODE_PRIVATE);
    editor = sharedPreferences.edit();

    editor.putInt("NightModeInt", NightMode);
    editor.apply();
}

That’s all you need to do to save the dark mode state of your whole app even when the app is terminated or killed by the OS.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement