Java 如何更改Android O/Oreo/api 26应用程序语言

Java 如何更改Android O/Oreo/api 26应用程序语言,java,android,locale,default,Java,Android,Locale,Default,我想更改应用程序的语言,这在API 26之前都可以正常工作 对于api>25,我放入Locale.setDefault(Locale.Category.DISPLAY,mynewlanglocale)之前setContentView(R.layout.activity\u main)但没有任何更改 不要对此做太多解释。这是可能的,但是我不建议以编程方式设置语言 安卓系统的设计使得系统用户界面和你的应用程序具有相同的语言,如果你以编程方式更改它,你将与系统发生冲突 相反,您可以通过添加不同的str

我想更改应用程序的语言,这在API 26之前都可以正常工作

对于api>25,我放入
Locale.setDefault(Locale.Category.DISPLAY,mynewlanglocale)之前
setContentView(R.layout.activity\u main)但没有任何更改


不要对此做太多解释。

这是可能的,但是我不建议以编程方式设置语言

安卓系统的设计使得系统用户界面和你的应用程序具有相同的语言,如果你以编程方式更改它,你将与系统发生冲突

相反,您可以通过添加不同的strings.xml语言来启用多语言支持,这将自动更改语言

我建议阅读这篇谷歌开发者文章:

如果您真的需要按程序进行更改,您可以执行以下操作

Locale locale = new Locale("en");
Locale.setDefault(locale);

Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
context.createConfigurationContext(config);
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
在SDK>=21上,您需要调用“Resources.updateConfiguration()”,否则资源将不会更新。


希望对您有所帮助。

您需要使用
getApplicationContext()
而不是
getContext()
更新配置
已被弃用,您应该使用
createConfigurationContext
。我是这样解决的:

    @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);
    }

这是一个完整的解决方案,适用于kitkat、棒棒糖、棉花糖、牛轧糖和奥利奥。只需按照以下步骤操作。

首先创建一个java类,如下所示

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());
  }
}
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");
}
现在,在要更改语言环境的地方单击按钮添加此代码段

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);
最后将下面的代码粘贴到Splash活动或Launching活动中

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();
    }

是的,在android Oreo中,本地化无法与updateconfiguration配合使用。但它在安卓N本身就被弃用了。在每个attachcontext中使用createconfiguration而不是updateconfiguration。这对我来说很好。试试这个

在您的活动中添加此

@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);
    }
}
在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);
}

针对Oreo之前的所有android版本更新

创建这样一个类

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;
}
applicationInstance = this; 
}

现在,当您从应用程序中选择语言时,请将语言代码保存在共享首选项中,如下所示

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());
  }
}
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");
}
这三个函数应该写在utilty类中(您的首选项)。然后,当您从应用程序中选择应用程序语言时,调用setSelectedLanguageId()函数并将语言id作为参数传递

这样,您就可以在应用程序中保存所选语言。现在在应用程序类中编写如下函数

public void initAppLanguage(Context context){
    LocaleUtils.initialize(context, PreferenceUtil.getSelectedLanguageId() );
}
这里PreferenceUtil是我的utilty类。应该用实用程序类函数替换它

您还应该在应用程序类中创建一个变量

private static Application applicationInstance;
public static synchronized Application getInstance() {
    return applicationInstance;
}
在应用程序类的onCreate方法中,将applicationInstance初始化为如下所示的应用程序上下文

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;
}
applicationInstance = this; 
现在在应用程序类中编写一个getter函数

private static Application applicationInstance;
public static synchronized Application getInstance() {
    return applicationInstance;
}
现在,当您启动第一个活动时,在活动的onCreate中调用此方法

Application.getInstance().initAppLanguage(this);
请记住,我们将活动的上下文传递给initAppLanguage()函数,而不是应用程序上下文。传递应用程序上下文不会使它在Oreo中工作(至少对我来说)

因此,当您选择语言时,请尝试完全重新启动应用程序。 你可以通过

Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
星触觉(i)


希望这对你有帮助

我也有同样的问题:自从安卓8.0+以来,我应用程序的某些部分不再改变语言。更新应用程序和活动上下文对我很有帮助。以下是MainActivity函数的一个示例:

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());
}

在使用了所有来源的所有解决方案后,我终于发现了我的问题。这让我生气了两天

每个人都知道,在Android Oreo(API 26)中,我们必须使用
createConfigurationContext
,但我的问题是将国家名称与本地名称一起使用

替换

en_USen

ar_AEar

fa_IRfa

我的问题解决了



希望能帮助他人

您的意思是想使用Kotlin?使用Java和Android Studio 2.3.3您可以更改构建中的API级别。gradle项目文件我的Min Sdk版本为API19,目标Sdk版本为API23@DroiDev他说的是电话里的文字语言,他所采取的方法在26年内不再有效。虽然这可能回答了这个问题,但最好解释答案的基本部分,可能还有OPs代码的问题。对不起,我不知道为什么,它对我有效。请记住,我们将活动的上下文传递给initAppLanguage()函数,而不是应用程序上下文。传递应用程序上下文不会使它在Oreo中工作(至少对我来说)。非常感谢。谢谢你的回答。为什么要这样检查:如果(Build.VERSION.SDK\u INT>Build.VERSION\u CODES.N\u MR1){}低版本呢?我们如何更改它们?我在其他部分也添加了较低版本的代码。在较低版本中,updateconfiguration方法对于语言更改来说已经足够了。我需要将此添加到我的所有活动中,还是只添加到我应用程序的主要活动中?二,。在attachBaseContext中,如何从SharedReferences检索语言?我试过了,但当我打开应用程序时,它崩溃了。这可以在应用程序类上完成吗?如果是,将有助于在所有活动中覆盖attachBaseContext@Rajalakshmiarumugam在Oreo设备s8上不为我工作。有人能帮我吗?超级简单,对我也有用。我测试了7.1和8.0。谢谢!在10和7.0tnx上煎锅。这对我有用。但这是更好的解决方案吗?如果这对您不起作用,并且您正在使用appcompat 1.1.0,请检查这是否对我起作用,但前提是我在onCreate和onResume中调用此方法