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

Posted

技术标签:

【中文标题】如何更改 Android O / Oreo / api 26 应用程序语言【英文标题】:How to change Android O / Oreo / api 26 app language 【发布时间】:2017-11-07 18:45:36 【问题描述】:

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

对于 api > 25,我将 Locale.setDefault(Locale.Category.DISPLAY, mynewlanglocale); 放在 setContentView(R.layout.activity_main); 之前,但没有任何变化。

docs 对此不做过多解释。

【问题讨论】:

你的意思是要使用 Kotlin? 使用 Java 和 android Studio 2.3.3 您在 build.gradle project 文件中更改 API 级别 我的 Min Sdk 版本是 API19,目标 Sdk 版本是 API23 @DroiDev 他在谈论手机上的文本语言,以及他所采用的方法在 26 岁时不再适用。 【参考方案1】:

我遇到了同样的问题:由于 Android 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());

【讨论】:

超级简单,对我也有用。我在 7.1 和 8.0 上测试过。 谢谢!炒锅 10 和 7.0 tnx.这对我有用。但这是更好的解决方案吗? 如果这对您不起作用并且您使用的是 appcompat 1.1.0,请检查此***.com/questions/55265834/… 这对我有用,但只有当我在 onCreate 和 onResume 中调用此方法时【参考方案2】:

是的,在 Android Oreo 本地化中,更新配置不能正常工作。但它在 android N 本身中已被弃用。在每个附加上下文中使用 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);

【讨论】:

感谢您的回答。为什么要这样检查: if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) 低版本呢?我们如何改变它们? 我在其他部分也添加了低版本的代码。而在低版本更新配置方法足以改变语言。 1.我需要将其添加到我的所有活动中还是只添加到我的应用程序的 MainActivity 中?和 2. 在 attachBaseContext 中,如何从 SharedPreferences 中检索语言?我试过了,但是当我打开它时应用程序崩溃了。 这可以在应用程序类上完成吗?如果是,这将有助于在所有活动中覆盖 attachBaseContext! @RajalakshmiArumugam 在 Oreo 设备 s8 上不适合我。谁能帮帮我?【参考方案3】:

updateConfiguration 已弃用,您应该使用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);
    

【讨论】:

【参考方案4】:

更新至奥利奥之前的所有 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;

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

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");

这三个函数应该写在一个 Utiltiy 类中(你的偏好)。然后当您从应用程序中选择应用程序语言时,调用 setSelectedLanguageId() 函数并将语言 id 作为参数传递。

这样,您已将所选语言保存在您的应用中。现在在你的应用程序类中写一个这样的函数

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

这里的 PreferenceUtil 是我的 Utiltiy 类。您应该用您的实用程序类函数替换它。

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

private static Application applicationInstance;

并在您的 Application 类的 onCreate 方法中,将 applicationInstance 初始化为这样的应用程序上下文

applicationInstance = this; 

现在在您的应用程序类中编写一个 getter 函数

public static synchronized Application getInstance() 
    return applicationInstance;

现在当你开始你的第一个活动时,在你的活动的 onCreate 中调用这个方法

Application.getInstance().initAppLanguage(this);

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

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

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

startActivity(i);

希望对您有所帮助!

【讨论】:

太棒了,它对我有用。下一行救了我——记住我们将活动的上下文传递给 initAppLanguage() 函数,而不是应用程序上下文。传递 Application 上下文不会使它在 Oreo 中工作(至少对我来说)。非常感谢。【参考方案5】:

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

Android 的设计使得 系统 UI 和您的应用具有相同的语言,如果您以编程方式更改它,您将与系统发生冲突

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

我建议阅读这篇 Google Developers 文章:

Supporting Different Languages and Cultures

如果您确实需要以编程方式更改它,您可以执行以下操作

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()',否则资源不会更新。

希望对你有帮助。

【讨论】:

【参考方案6】:

这里也有适用于 kitkat、Lollipop、Marshmallow、Nougat 和 Oreo 的完整解决方案。只需按照以下所有步骤操作即可。

首先创建一个如下所示的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());
  

现在在按钮上添加这个 sn-p 点击您要更改语言环境的位置

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 Activity或者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();
    

【讨论】:

【参考方案7】:

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

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

替换

zh_CN with zh

ar_AE ar

fa_IR fa

我的问题解决了。

希望对某人有所帮助

【讨论】:

【参考方案8】:

您需要使用getApplicationContext() 而不是getContext()

【讨论】:

虽然这可能会回答这个问题,但最好解释一下答案的基本部分,以及 OPs 代码可能存在什么问题。 对不起,我不知道为什么

以上是关于如何更改 Android O / Oreo / api 26 应用程序语言的主要内容,如果未能解决你的问题,请参考以下文章

Android Nougat,Oreo - 如何将长按动作添加到快速切换?

AlarmManager和BroadcastReceiver的LocalNotification未在Android O(oreo)中启动

如何在 Android Oreo 中管理来自未知来源的安装?

Android Studio 无法识别 Oreo 的最新版本代码或新窗口类型

Android Oreo如何知道FCM消息已经到来?

我的 MainActivity 在使用 android 旧版本(例如 oreo)时滞后,但在最新版本中运行良好,如何解决?