Search code examples
androidconfigurationreloadpreferenceactivity

Android update language in preference activity


In my android app i have a preference activity which let's the user override the app's language. To achieve this I call this function in every activity's onResume() and then reset the content view:

    public static void checkOverrideSystemLanguage(Context context) {
    SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(context);

    // Check if system's language setting needs to be overridden
    boolean overrideSystemLanguage = prefs.getBoolean(context
            .getString(R.string.pref_key_chkbx_override_system_language),
            false);

    if (overrideSystemLanguage) {

        // Get language selection and possible languages
        String localeString = prefs.getString(
                context.getString(R.string.pref_key_list_languages), "");
        List<String> possibleLanguages = Arrays.asList(context
                .getResources().getStringArray(
                        R.array.pref_values_list_languages));

        if (possibleLanguages.contains(localeString)) {

            // Change language setting in configuration
            Locale locale = new Locale(localeString);
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            context.getResources().updateConfiguration(config,
                    context.getResources().getDisplayMetrics());
        }
        // Use default language
        else {
            overrideSystemLanguage = false;
        }
    }

    // Use default language
    if (!overrideSystemLanguage) {
        context.getResources().updateConfiguration(
                Resources.getSystem().getConfiguration(),
                context.getResources().getDisplayMetrics());
    }
}

In every activity it works perfectly fine. In the preference activity, however, when the user changes the language it does not get updated right away, because there is no setContentView() method. The user has to go back to the previous activity and start the preferences activity again to see the language change reflected.

I tried the following in a onPreferenceChange() listener:

  1. Updating the configuration, removing and readding the preferences:

    checkOverrideSystemLanguage(this);      
    // Remove all preferences and add them to update the language
    getPreferenceScreen().removeAll();
    addPreferencesFromResource(R.xml.preferences);
    
  2. Updating the configuration and calling onCreate(null)

  3. Finishing and restarting the activity

    finish();
    startActivity(new Intent(this, PreferencesActivity.class));
    

Thanks for your help!


Solution

  • I had a similar problem, I solved in this way (as you said: finishing and restarting activity). It works!

        public class OptionsActivity extends PreferenceActivity implements YesNoDialogPreference.YesNoDialogListener, SharedPreferences.OnSharedPreferenceChangeListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            //Options Setting
            final SharedPreferences prefs = getSharedPreferences(OptionsUtility.PREFERENCE_NAME, MODE_PRIVATE);
            String language = prefs.getString(OptionsUtility.PREFERENCE_LANGUAGE, OptionsUtility.DEFAULT_LANGUAGE);
    
            //Update locale
            OptionsUtility.updateLanguage(this, language);
            prefs.registerOnSharedPreferenceChangeListener(this);
    
            getPreferenceManager().setSharedPreferencesMode(MODE_PRIVATE);
            getPreferenceManager().setSharedPreferencesName(OptionsUtility.PREFERENCE_NAME);
    
            // Load the preferences from an XML resource
            addPreferencesFromResource(R.xml.preferences);
    
            Preference eraseGameButton = getPreferenceManager().findPreference(OptionsUtility.PREFERENCE_ERASE_GAME);
            if (eraseGameButton != null) {
                YesNoDialogPreference yesNo = (YesNoDialogPreference)eraseGameButton;
                yesNo.setListener(this);
            }
    
            Preference configureKeyboardPref = getPreferenceManager().findPreference("keyconfig");
            if (configureKeyboardPref != null) {
                //KeyboardConfigDialogPreference config = (KeyboardConfigDialogPreference)configureKeyboardPref;
                //config.setPrefs(getSharedPreferences(MemodroidCoreActivity.PREFERENCE_NAME, MODE_PRIVATE));
                //config.setContext(this);
            }
    
        }
    
    
        public void onDialogClosed(boolean positiveResult) {
            if (positiveResult) {
                DatabaseScoreManager dbsManager = new DatabaseScoreManager(getApplicationContext());
                dbsManager.resetHighScores();
                Toast.makeText(this, R.string.toast_highScoresReset,Toast.LENGTH_SHORT).show();
            }
        }
    
    
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) {
            restartActivity();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
        }
    
        private void restartActivity() {
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }
    
        @Override
        public void onBackPressed() {
            finish();
        }
    }