Android language changes after rotation
Asked Answered
H

3

9

When my app is installed, on first run it asks user to choose language; But if user starts app on second time, language is set automatically (to previously selected one).

Problem is that, on first run when user selects language, app still is in English (no matter what language user selects), but if I rotate device, then language is changed to correct one (to selected one). Same problem occurs on apps second run; App starts in English, but after rotation language is changed to correct one.

Any suggestions? thank you in advance

here code from MainActivity from where I change language:

private void initApp() {
        if (Settings.getLanguage().equals("")){ 
            String[] items = { getResources().getString(R.string.lang_eng), getResources().getString(R.string.lang_geo)};
            showDialogSingleChoise(items, getResources().getString(R.string.select_language_title), 0, false, false, this.languageSelectedListener, this.languageConfirmedListener, null);
        } else {        
            System.out.println("initApp: " + Settings.getLanguage());

            Settings.setLanguage(MainActivity.this.getResources(), Settings.getLanguage());
            appVersionCheck();
        }
    }

private OnClickListener languageConfirmedListener = new OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {
        Settings.setLanguage(MainActivity.this.getResources(), MainActivity.this.language);
        appVersionCheck();
    }
};

and here is code fragment from settings:

public static void setLanguage(Resources res, String langString){
        System.out.println("lang in pref: " + langString);
        setStringProperty(PREFS_LANG ,langString);
        MainApp.getInstance().setLocale(res);
    }

Here is my Application class:

public class MainApp extends Application {
    private static volatile MainApp instance;

    public static MainApp getInstance() {
        return MainApp.instance;
    }

    @Override
    public void onCreate() {
        MainApp.instance = this;
        super.onCreate();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setLocale(this.getResources());
    }

    public void setLocale(Resources res) {
        System.out.println("initApp: " + Settings.getLanguage() == "" ? Settings.LANG_EN : Settings.getLanguage());
        Configuration conf = res.getConfiguration();
        conf.locale = new Locale(Settings.getLanguage() == "" ? Settings.LANG_EN : Settings.getLanguage());
        res.updateConfiguration(conf, res.getDisplayMetrics());
    }
}

and lastly, this is manifest (do I need android:configChanges="locale" at all?):

<application
        android:name="...MainApp"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="....MainActivity"
            android:configChanges="locale"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
Harim answered 5/11, 2015 at 10:16 Comment(2)
have you used different string files for your different languages with preferred value folder name like values-fr for French?Lanfranc
you dont need to call onConfigurationChanged()...in my app i just used Resources resources = getResources(); Configuration configuration = resources.getConfiguration(); configuration.locale = new Locale("en"); resources.updateConfiguration(configuration,dm); and work perfect for meLanfranc
A
3

Your configuration cannot be applied until your Activity is restarted,so when you click to change locale it cannot be applied at once,but when you rotate your screen the Activity restarts thus applies your configuration changes.

You should restart your Activity manually after click to change the locale,and here is a code demo to restart your Activity:

private void restartActivity() {
    Intent intent = getIntent();
    finish();
    startActivity(intent);
    }

And I think you should not write the changing locale code in your Application class,it should be written in the Activity that you use to change locale.

As for applying new locale in the future app opening,you can use SharedPreferences to save your configuration and get the locale value every time your application is opened and apply it.

You can get the SharedPreferences and apply the locale in the Application class's onCreate() method.

And you certainly should write the android:configChanges="locale|orientation" in your manifest and the onConfigurationChanged() method is also necessary.Because if you rotate the screen or do anything else that change the system configuration that can restart your Activity,the default locale will be applied.So you should make sure the new locale is applied every time the configuration is changed.

For more details about how to deal with locale change,you can read this: How to refresh activity after changing language (Locale) inside application

Alrzc answered 5/11, 2015 at 11:7 Comment(1)
This solution didn't work for me. The problem was because there was a race condition between the finish and startActivity. If startActivity happened first, the language wouldn't change until I rotated the screen. My solution was to set a shouldRestartAfterDestroy property to true and then call finish. In the activity's onDestroy, if shouldRestartAfterDestroy == true, I call startActivity.Stumper
P
1

I override my ConfigChange in application like following and I call setLocale function each time configurationChanged :

public class AioApplication extends Application {

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setLocale(LocaleUtility.getLocale());
    }

    @Override
    public void onCreate() {
        super.onCreate();

        LocaleUtility.initialize(this);
    }



    private void setLocale(Locale locale) {
        Configuration conf = getBaseContext().getResources().getConfiguration();
        conf.locale = locale;
        getBaseContext().getResources().updateConfiguration(conf, getResources().getDisplayMetrics());
        Configuration systemConf = Resources.getSystem().getConfiguration();
        systemConf.locale = locale;
        Resources.getSystem().updateConfiguration(systemConf, Resources.getSystem().getDisplayMetrics());
        Locale.setDefault(locale);
    }

}
Penna answered 30/7, 2016 at 12:25 Comment(0)
C
0

It looks like your setLocale updates the configuration of the app. But you've asked to handle that configuration change manually with android:configChanges="locale"

If you remove that line, your configuration change may work.

One thing I think you can remove is you onConfigurationChange method from your application object. Does this not lead you down an infinite loop currently?

Update: looks like manually changing the locale configuration doesn't cause an activity restart. have a look at this: Changing Locale within the app itself Although I'd be really careful about using android:configChanges if you can

Cheek answered 5/11, 2015 at 15:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.