How to change Android O / Oreo / api 26 app language

前端 未结 8 1471
深忆病人
深忆病人 2020-12-01 04:37

I want to change the language of the app and this works fine until API 26.

For api > 25 I put Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale);

相关标签:
8条回答
  • 2020-12-01 05:01

    Yes in android Oreo localization is not working fine with updateconfiguration. But it is deprecated in android N itself. Instead of updateconfiguration use createconfiguration in each attachcontext. it is working fine for me. Try this...

    In you activity add this..

    @Override
    protected void attachBaseContext(Context newBase) {
        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            super.attachBaseContext(MyContextWrapper.wrap(newBase, "ta"));
        }
        else {
            super.attachBaseContext(newBase);
        }
    }
    

    In MyContextWrapper.java

     public static ContextWrapper wrap(Context context, String language) {
        Resources res = context.getResources();
        Configuration configuration = res.getConfiguration();
        Locale newLocale = new Locale(language);
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            configuration.setLocale(newLocale);
            LocaleList localeList = new LocaleList(newLocale);
            LocaleList.setDefault(localeList);
            configuration.setLocales(localeList);
            context = context.createConfigurationContext(configuration);
    
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(newLocale);
            context = context.createConfigurationContext(configuration);
    
        } else {
            configuration.locale = newLocale;
            res.updateConfiguration(configuration, res.getDisplayMetrics());
        }
    
        return new ContextWrapper(context);
    }
    
    0 讨论(0)
  • 2020-12-01 05:12

    I had the same problem: since Android 8.0+ some parts of my app did't change their language anymore. Updating of both application and activity context helps me. Here is an example of MainActivity function:

    private void setApplicationLanguage(String newLanguage) {
        Resources activityRes = getResources();
        Configuration activityConf = activityRes.getConfiguration();
        Locale newLocale = new Locale(newLanguage);
        activityConf.setLocale(newLocale);
        activityRes.updateConfiguration(activityConf, activityRes.getDisplayMetrics());
    
        Resources applicationRes = getApplicationContext().getResources();
        Configuration applicationConf = applicationRes.getConfiguration();
        applicationConf.setLocale(newLocale);
        applicationRes.updateConfiguration(applicationConf, 
        applicationRes.getDisplayMetrics());
    }
    
    0 讨论(0)
  • 2020-12-01 05:13

    You need to use getApplicationContext() instead of getContext()

    0 讨论(0)
  • 2020-12-01 05:15

    updateConfiguration is deprecated and you should use createConfigurationContext. I solved it this way:

        @Override
        protected void attachBaseContext(Context newBase) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Configuration config = newBase.getResources().getConfiguration();
                //Update your config with the Locale i. e. saved in SharedPreferences
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(newBase);
                String language = prefs.getString(SP_KEY_LANGUAGE, "en_US");
                Locale.setDefault(locale);
                config.setLocale(new Locale(language));
                newBase = newBase.createConfigurationContext(config);
            }
            super.attachBaseContext(newBase);
        }
    
    0 讨论(0)
  • 2020-12-01 05:18

    Here is complete solution worked for kitkat, Lollipop, Marshmallow, Nougat and Oreo too. Just follow all below step.

    First create a java class like below

    import android.content.Context;
    import android.content.res.Configuration;
    import java.util.Locale;
    public class LocaleUtils {
    public static void updateConfig(Context mContext, String sLocale) {
        Locale locale = new Locale(sLocale);
        Locale.setDefault(locale);
        Configuration config = mContext.getResources().getConfiguration();
        config.locale = locale;
        mContext.getResources().updateConfiguration(config,
                mContext.getResources().getDisplayMetrics());
      }
    }
    

    Now add this snippet on Button click where you want to change locale

    String lang="hi";//pass your language here
    SharedPreferences preferences =  PreferenceManager.getDefaultSharedPreferences(mContext);
                            SharedPreferences.Editor editor = preferences.edit();
                            editor.clear();
                            editor.putString("lang", lang");
                            editor.putBoolean("langSelected", true);
                            editor.apply();
                            LocaleUtils.updateConfig(mContext,lang);
                            Intent intent = mContext.getIntent();
                            mContext.overridePendingTransition(0, 0);
                            mContext.finish();
                            intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            mContext.overridePendingTransition(0, 0);
                            mContext.startActivity(intent);
    

    Finally paste the below code in Splash Activity or in Launching Activity.

    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        String lang = preferences.getString("lang", "");
        boolean langSelected = preferences.getBoolean("langSelected", false);
        SharedPreferences.Editor editor = preferences.edit();
        if (langSelected) {
            editor.clear();
            editor.putString("lang", lang);
            editor.putBoolean("langSelected", true);
            editor.apply();
            LocaleUtils.updateConfig(this,lang);
        } else {
            LocaleUtils.updateConfig(this, Locale.getDefault().getLanguage());
            editor.clear();
            editor.putString("lang", Locale.getDefault().getLanguage());
            editor.putBoolean("langSelected", false);
            editor.apply();
        }
    
    0 讨论(0)
  • Updated For All android versions till Oreo

    Create a class like this

    public class LocaleUtils {
    
    @Retention(RetentionPolicy.SOURCE)
    @StringDef({ENGLISH, FRENCH, SPANISH})
    public @interface LocaleDef {
        String[] SUPPORTED_LOCALES = {ENGLISH, FRENCH, SPANISH};
    }
    
    public static final String ENGLISH = "en";
    public static final String FRENCH = "fr";
    public static final String SPANISH = "es";
    
    
    public static void initialize(Context context) {
        setLocale(context, ENGLISH);
    }
    
    public static void initialize(Context context, @LocaleDef String defaultLanguage) {
        setLocale(context, defaultLanguage);
    }
    
    
    public static boolean setLocale(Context context, @LocaleDef String language) {
        return updateResources(context, language);
    }
    
    private static boolean updateResources(Context context, String language) {
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        context.createConfigurationContext(configuration);
        configuration.locale = locale;
        resources.updateConfiguration(configuration, resources.getDisplayMetrics());
        return true;
    }
    

    }

    Now when you select the language from your app, Save the language code in Shared Preference like below

    private static SharedPreferences getDefaultSharedPreference(Context context) {
        if (PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext()) != null)
            return PreferenceManager.getDefaultSharedPreferences(Application.getInstance().getApplicationContext());
        else
            return null;
    }
    
     public static void setSelectedLanguageId(String id){
        final SharedPreferences prefs = getDefaultSharedPreference(Application.getInstance().getApplicationContext());
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString("app_language_id", id);
        editor.apply();
    }
    
    public static String getSelectedLanguageId(){
        return getDefaultSharedPreference(Application.getInstance().getApplicationContext())
                .getString("app_language_id", "en");
    }
    

    These three functions should be written inside a Utiltiy class(your preference). Then when you select the app language from the app, call the setSelectedLanguageId() function and pass the language id as parameter.

    This way you have saved the selected language in your app. Now in your application class write a function like this

    public void initAppLanguage(Context context){
        LocaleUtils.initialize(context, PreferenceUtil.getSelectedLanguageId() );
    }
    

    Here the PreferenceUtil is my Utiltiy class. You should replace it with your utility class function.

    You should also create a variable in your application class

    private static Application applicationInstance;
    

    and in your Application class's onCreate method, initialise applicationInstance to be the applications context like this

    applicationInstance = this; 
    

    Now write a getter function in your application class

    public static synchronized Application getInstance() {
        return applicationInstance;
    }
    

    And now when you start your first activity, call this method in your activity's onCreate

    Application.getInstance().initAppLanguage(this);
    

    Remember that we are passing the activity's context to the initAppLanguage() function, not the application context. Passing the Application context won't make it work in Oreo(atleast for me).

    So when you select the language try to restart your application completely. You can acheive this by

    Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
    

    startActivity(i);

    Hope this helps you!

    0 讨论(0)
提交回复
热议问题