Search code examples
androidconfigurationruntimesharedpreferenceslocale

Changing app language in runtime


I'm trying to implement app language switch on the runtime, once the user made language changes in app preferences. I have this code in my PreferenceFragment:

public class Fragment_Preferences extends PreferenceFragment {

private SharedPreferences.OnSharedPreferenceChangeListener prefListener;

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);

    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());

    prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {

            Log.i("Pref changed", "Settings key changed: " + key);
            if(key.equals("language_preference"))
            {
                String system_language = Locale.getDefault().getLanguage().toUpperCase();
                String preference_language = Common_Methods.get_preference_language(getActivity());
                Toast.makeText(getActivity(), "Pref changed: "+preference_language, Toast.LENGTH_SHORT).show();
                Common_Methods.set_app_interface_language(getActivity(), system_language, preference_language);
            }

        }
    };
    prefs.registerOnSharedPreferenceChangeListener(prefListener);
}

}

This is my set_app_interface_language method in Common_Methods class:

public static void set_app_interface_language(Context context, String system_language, String preference_language)
{
    if(!preference_language.equals(system_language))
    {
        Locale locale = new Locale(preference_language.toLowerCase());
        Locale.setDefault(locale);
        Configuration config = new Configuration();
        config.locale = locale;
        context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
    }
}

I get the Toast message when I change language in preferences. I know that this method works since I call it also from my Fragment_Main. But the language doesn't change on the runtime - I have to exit the app and reopen it, only then I see the changes.

So how can I make the app language change on the runtime, without restarting the app? Thanks!


Solution

  • OK, I think I solved this problem: I call for Common_Methods.set_app_interface_language not in SharedPreferences.OnSharedPreferenceChangeListener, but rather in onRestart method of my Fragment_Main.

    I also changed set_app_interface_language to return new config. And once it's returned - I pass it to onConfigurationChanged method to recreate fragment. Now, I did ran into Performing pause of activity that is not resumed... error message once my device's screen turned off. After googling a little about it, I realized that it's non-fatal exception, but I still used Handler to postpone recreate() for 1 millisecond and let the Fragment restart properly. I also set another method in my Common_Methods to check if there were any changes made to the app language and recreate the fragment only if the method returns true; I call this method in onRestart That gave the app some performance boost, since now there's no need to recreate the fragment every time the app restarts.