1

How to restart the application after onSharedPreferenceChanged has been called?

ActivityPreferences.java:

[..]
public static class FragmentPreferences extends PreferenceFragment {
        private Context context;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            context = getActivity();
            PreferenceManager.setDefaultValues(getActivity(), R.xml.preferences, false);
            addPreferencesFromResource(R.xml.preferences);

            final SharedPreferences sp = context.getSharedPreferences("PREFERENCE_KEY", Context.MODE_PRIVATE);
            SharedPreferences.OnSharedPreferenceChangeListener spChanged = new SharedPreferences.OnSharedPreferenceChangeListener() {
                @Override
                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
                    context.finish();
                    startActivity(new Intent(ActivityPreferences.this, ActivityLogin.class));
                }
            };
        }
    }

That's what I tried, but I can't call finish().

I want to change the theme, if the listpreference s1_theme has been set to light/dark:

ActivityMain.java:

@Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Context context = getApplicationContext();
        final SharedPreferences sp = context.getSharedPreferences("PREFERENCE_KEY", Context.MODE_PRIVATE);
        if (sp.getString("s1_theme", "-1") == "light"){
                setTheme(R.style.AppTheme_BaseLight);
        } else {
            setTheme(R.style.AppTheme_BaseDark);
        }
        setContentView(R.layout.activity_main);
        [..]
Tomblarom
  • 1,429
  • 1
  • 15
  • 38

4 Answers4

4

Try this code... This will restart the MainActivity...

                    this.finish();
                    Intent refresh = new Intent(this, MainActivity.class);
                    startActivity(refresh);

create a method in MainActivity with this code and call this from the fragment class which you want to restart by passing the context...

Rishad Appat
  • 1,786
  • 1
  • 15
  • 30
1

For themes changing, I think you should have a global variable, which you would check for each activity (in its onResume function) vs the last one it used, and then restart itself if they are different.

Here's the code to restart the activity:

  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  public static void restartActivity(final Activity activity)
    {
    if(android.os.Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
      activity.recreate();
    else
      {
      new Handler().post(new Runnable()
      {
      @Override
      public void run()
        {
        activity.overridePendingTransition(0,0);
        activity.startActivity(activity.getIntent());
        }
      });
      activity.finish();
      }
    }
android developer
  • 114,585
  • 152
  • 739
  • 1,270
1

I used themes completely wrong :) To change themes/styles dynamically you can follow these steps:

1. Define themes:

<!-- values/attr.xml -->
<resources>
    <attr name="testcolor" format="color" />
    ..
</resources>

<!-- values/styles.xml -->
<resources>
    <style name="AppTheme.Dark" parent="Theme.AppCompat.NoActionBar">
        <item name="backgroundLinearLayout">@color/backgroundLinearLayout</item>
        ..
    </style>

    <style name="AppTheme.Light" parent="Theme.AppCompat.NoActionBar">
        <item name="backgroundLinearLayout">@color/backgroundLinearLayout</item>
        ..
    </style>
</resources>

<!-- layout/layout_1.xml -->
<LinearLayout
   ..
   android:background="?attr/backgroundLinearLayout">
</LinearLayout>

2. Create/Edit the SettingsActivity

<!-- xml/preference_main.xml -->

<PreferenceScreen>
    <PreferenceCategory android:title="Themes">
        <SwitchPreference
            android:defaultValue="false"
            android:key="theme_preference_key"
            android:title="Enable for darkmode"/>
    </PreferenceCategory>
    ..
</PreferenceScreen>

// SettingsActivity Class

public class SettingsActivity extends PreferenceActivity implements Preference.OnPreferenceChangeListener {
    public static final int RESULT_CODE_THEME_UPDATED = 1;
    private SharedPreferences sp;
    private TypedArray ta;
    private int backgroundLinearLayout;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        context = getApplicationContext();
        sp = PreferenceManager.getDefaultSharedPreferences(this);
        changeTheme(sp.getBoolean("theme_preference_key", false));
        super.onCreate(savedInstanceState);
        findPreference("theme_preference_key").setOnPreferenceChangeListener(new RefershActivityOnPreferenceChangeListener(RESULT_CODE_THEME_UPDATED));
        ..
    }

    private void changeTheme(Object newValue) {
        int[] attrs = {android.R.attr.backgroundLinearLayout};
        if (sp.getBoolean("theme_preference_key", false)) {
            setTheme(R.style.AppTheme_Dark);
            ta = obtainStyledAttributes(R.style.AppTheme_Dark, attrs);
            backgroundLinearLayout= ta.getColor(0, Color.BLACK);
        } else {
            setTheme(R.style.AppTheme_Light);
            ta = obtainStyledAttributes(R.style.AppTheme_Light, attrs);
            backgroundLinearLayout= ta.getColor(0, Color.BLACK);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ta.recycle();
    }

    private class RefershActivityOnPreferenceChangeListener implements OnPreferenceChangeListener {
        private final int resultCode;

        public RefershActivityOnPreferenceChangeListener(int resultCode) {
            this.resultCode = resultCode;
        }

        @Override
        public boolean onPreferenceChange(Preference p, Object newValue) {
            setResult(resultCode);
            finish();
            startActivity(getIntent());
        return true;
    }
}

//MainActivity Class

public class ActivityMain extends AppCompatActivity {
    private int SETTINGS_ACTION = 1;
    private SharedPreferences sp;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        context = getApplicationContext();
        sp = PreferenceManager.getDefaultSharedPreferences(this);
        setTheme((sp.getBoolean("s1_theme", false)) ? R.style.AppTheme_Dark : R.style.AppTheme_Light);
        super.onCreate(savedInstanceState);
        ..
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == SETTINGS_ACTION) {
            if (resultCode == SettingsActivity.RESULT_CODE_THEME_UPDATED) {
                finish();
                startActivity(getIntent());
                return;
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}
Tomblarom
  • 1,429
  • 1
  • 15
  • 38
0

You can launch intent with specific action, lets say ACTION_REFRESH.

Intent intent = new Intent(context, MainActivity.class);
intent.setAction(MainActivity.ACTION_REFRESH);
context.startActivity(intent);

Then handle this intent and its action on MainActivity#onCreate() and MainActivity#onNewIntent() and launch the new one with Intent.FLAG_ACTIVITY_CLEAR_TOP flag

protected void onNewIntent(Intent intent) {
  if (MainActivity.ACTION_REFRESH.equals(intent.getAction()) {
    finish();
    Intent intent = new Intent(context, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    context.startActivity(intent);
  }
}

protected void onCreate(Bundle savedInstanceState) {
  // Same thing
}

You'll probably need to tune this code somehow, but hope you get the idea.

Sergey Dmitriev
  • 454
  • 3
  • 13