Search code examples
androidandroid-activitylocale

Fix resources when language is changed


I already know how to change the language of my application (updating the configuration). My code also check if the configuration is changed by the system and "fix it" in the ´onCreate´ method. I even have created a ListPreference to let the user decide the language with one that my app supports (and saves the decision).

Let's say I have 3 activities (A, B and SettingsActivity). Activity A can start activities B and SettingsActivity. Activity B can start SettingsActivity. If the user changes the language inside SettingsActivity, I can update its resources (in this case Strings) without any problem using this code:

//if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
// Disabled because it blinks and looks bad
// recreate();
// } else {
    startActivity(getIntent());
    finish();
    overridePendingTransition(0, 0);
// }

However, I'm unable to change the already open activities because I have no reference to them from SettingsActivity.

My question: is there any clean way to update the resources or recreate the already open activities? If I don't find a better solution, my approach will be one of the above:

  1. Start activities using startActivityForResultand return a code to trigger the code I already use to recreate the activity.
  2. Check inside the onResume method if the current language has changed and do the same thing.

Solution

  • At the end what I did was this:

    @Override
    protected void onStart() {
        super.onStart();
        if (!locale.equals(getResources().getConfiguration().locale)) {
            finish();
            startActivity(getIntent());
            overridePendingTransition(0, 0);
            return;
        }
    }
    

    Where locale is a variable assigned in my onCreate method:

    private Locale locale;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((Application) getApplication()).refreshLanguage();
        locale = getResources().getConfiguration().locale;
        setContentView(R.layout.activity_main);
        //moar code
    }
    

    Finally, for the sake of posting code, here is my refreshLanguage method(s):

    boolean refreshLanguage() {
        return refreshLanguage(PreferenceManager.getDefaultSharedPreferences(this));
    }
    
    boolean refreshLanguage(SharedPreferences sharedPreferences) {
        if (sharedPreferences.contains("language")) {
            int languageIndex = Integer.parseInt(sharedPreferences.getString("language", "0"));
            if (!getResources().getConfiguration().locale.equals(languages[languageIndex])) {
                Configuration config = new Configuration();
                config.locale = languages[languageIndex];
                getResources().updateConfiguration(config, null);
                return true;
            }
        }
        return false;
    }
    

    Notice that I use onStart rather than onResume because I'm not switching between transparent activities or using dialogs.