无法使用 Oreo android 更改我的应用程序的语言

2023-12-09

(EDIT)

我使用了区域设置更改的解决方案来更改应用程序的语言,但它在奥利奥中不起作用。它在我的三星 S4 上运行良好,但在我的 S9 上运行不佳。

所以我正在像这样进行区域设置更改:

   public void initAppLanguages(Context context, String lang){
        PreferenceUtil.setSelectedLanguageId(lang);
        LocaleUtils.setLocale(context, lang );
        MyApplication.reouvrir=1;
        Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
        this.finishAffinity();
        finish();
        startActivity(i);


    }

我的 LocaleUtils 类:

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

我的 PreferenceUtil 类:

public class PreferenceUtil {
    private static SharedPreferences getDefaultSharedPreference(Context context) {
        if (PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance().getApplicationContext()) != null)
            return PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance().getApplicationContext());
        else
            return null;
    }

    public static void setSelectedLanguageId(String id){
        final SharedPreferences prefs = getDefaultSharedPreference(MyApplication.getInstance().getApplicationContext());
        SharedPreferences.Editor editor = prefs.edit();
        editor.putString("app_language_id", id);
        editor.apply();
    }

    public static String getSelectedLanguageId(){
        return getDefaultSharedPreference(MyApplication.getInstance().getApplicationContext())
                .getString("app_language_id", "en");
    }
}

子活动的区域设置变化如下:

MyApplication.initAppLanguage(mContext);

我究竟做错了什么?为什么它在奥利奥中不起作用?


请按照以下步骤操作:

注意:我假设您在值文件夹中为不同的英语、西班牙语和法语创建了不同的字符串文件。 (即res目录中每个values-en、values-es、values-fr文件夹中的strings.xml文件)

添加此文件:LocaleHelper.java

package com.test;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;
import android.preference.PreferenceManager;
import java.util.Locale;

public class LocaleHelper {

private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";

public static Context onAttach(Context context) {
    String lang = getPersistedData(context, Locale.getDefault().getLanguage());
    return setLocale(context, lang);
}

public static Context onAttach(Context context, String defaultLanguage) {
    String lang = getPersistedData(context, defaultLanguage);
    return setLocale(context, lang);
}

public static String getLanguage(Context context) {
    return getPersistedData(context, Locale.getDefault().getLanguage());
}

public static Context setLocale(Context context, String language) {
    persist(context, language);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return updateResources(context, language);
    }

    return updateResourcesLegacy(context, language);
}

private static String getPersistedData(Context context, String defaultLanguage) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    return preferences.getString(SELECTED_LANGUAGE, defaultLanguage);
}

private static void persist(Context context, String language) {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = preferences.edit();

    editor.putString(SELECTED_LANGUAGE, language);
    editor.apply();
}

@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, String language) {
    Locale locale = new Locale(language);

    Configuration configuration = context.getResources().getConfiguration();
    LocaleList localeList = new LocaleList(locale);
    localeList.setDefault(localeList);
    configuration.setLocales(localeList);

    return context.createConfigurationContext(configuration);
}

@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    Resources resources = context.getResources();

    Configuration configuration = resources.getConfiguration();
    configuration.locale = locale;

    resources.updateConfiguration(configuration, resources.getDisplayMetrics());

    return context;
}
}

添加文件:LanguageUtil.java

package com.test;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Log;

import java.util.Locale;

public class LanguageUtil {
public static void changeLanguageType(Context context, Locale localelanguage) {
    Log.i("=======", "context = " + context);
    Resources resources = context.getResources();
    DisplayMetrics dm = resources.getDisplayMetrics();
    Configuration config = resources.getConfiguration();
    // Application user selects language
    // reference https://developer.android.com/reference/android/content/res/Configuration.html
    if (VersionUtils.isAfter24()) {
        config.setLocale(localelanguage);
    } else {
        config.locale = localelanguage;
        resources.updateConfiguration(config, dm);
    }
}

public static Locale getLanguageType(Context context) {
    Log.i("=======", "context = " + context);
    Resources resources = context.getResources();
    Configuration config = resources.getConfiguration();
    // Application user selects language
    if (VersionUtils.isAfter24()) {
        return config.getLocales().get(0);
    } else {
        return config.locale;
    }
}
}

添加文件:MyContextWrapper.java

package com.test;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.LocaleList;

import java.util.Locale;

public class MyContextWrapper extends ContextWrapper {

public MyContextWrapper(Context base) {
    super(base);
}

@TargetApi(Build.VERSION_CODES.N)
public static ContextWrapper wrap(Context context, Locale newLocale) {
    Resources res = context.getResources();
    Configuration configuration = res.getConfiguration();

    if (VersionUtils.isAfter24()) {
        configuration.setLocale(newLocale);

        LocaleList localeList = new LocaleList(newLocale);
        LocaleList.setDefault(localeList);
        configuration.setLocales(localeList);

        context = context.createConfigurationContext(configuration);

    } else if (VersionUtils.isAfter17()) {
        configuration.setLocale(newLocale);
        context = context.createConfigurationContext(configuration);

    } else {
        configuration.locale = newLocale;
        res.updateConfiguration(configuration, res.getDisplayMetrics());
    }

    return new ContextWrapper(context);
}
}

添加文件:VersionUtils.java

package com.test;

import android.os.Build;
import android.support.annotation.RequiresApi;

public final class VersionUtils {

@RequiresApi(Build.VERSION_CODES.N_MR1)
public static boolean isAfter25() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1;
}

@RequiresApi(Build.VERSION_CODES.N)
public static boolean isAfter24() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
}

public static boolean isAfter23() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}

public static boolean isAfter22() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1;
}

public static boolean isAfter21() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}

public static boolean isAfter20() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH;
}

public static boolean isAfter19() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}

public static boolean isAfter18() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
}

public static boolean isAfter17() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
}

public static boolean isAfter16() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}

public static boolean isAfter14() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}

public static boolean isAfter13() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2;
}

public static boolean isAfter11() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}

public static boolean isAfter9() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
}

public static boolean isAfter8() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
}

public static boolean isAfter5() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR;
}
}

现在创建 Prefs 文件:Prefs.kt(这是 Kotlin 类文件) 注意:您可以使用自己的首选项创建和检索代码。

包 com.test

import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.Editor

class Prefs private constructor(private val context: Context) {
private val prefranceName = "testPrefs"

companion object {

    private fun getPrefs(context: Context): SharedPreferences {
        return context.getSharedPreferences(context.packageName, 0)
    }

    fun clearDefaultShared(key: String, context: Context) {
        val e = getPrefs(context).edit()
        e.remove(key)
        e.apply()
    }

    fun setString(key: String, sunDefult: String, context: Context) {
        val e = getPrefs(context).edit()
        e.putString(key, sunDefult)
        e.apply()
    }

    fun getString(key: String, sunDefult: String, context: Context): String? {
        return getPrefs(context).getString(key, sunDefult)
    }

    fun clearAll(context: Context) {
        val editor = getPrefs(context).edit()
        editor.clear()
        editor.commit()
    }
}
}

现在创建一个类 TestApp,它扩展了 Application 类。 这将用于保存应用程序重新启动时要应用的最后选择的语言。注意:不要忘记将此应用程序类名“TestApp”添加到 AndroidManifest.xml 标签中。

添加文件:测试应用程序.kt

package com.test

import android.app.Application
import com.test.LanguageUtil
import com.test.Prefs
import java.util.*

class TestApp : Application() {

override fun onCreate() {
    super.onCreate()
    dbAdapter = DBAdapter(applicationContext)
    dbAdapter.openDataBase()

    // Set Language Because Local will not be saved every time the app restarts after it is completely logged out
    var languageType = Prefs.getString("languageType", "en", this@TestApp).toString()


    if (languageType == "fr") {
        LanguageUtil.changeLanguageType(this, Locale.FRENCH)
    } else if (languageType == "es") {
        LanguageUtil.changeLanguageType(this, Locale("es",""))
    } else {
        LanguageUtil.changeLanguageType(this, Locale.ENGLISH)
    }

}
}

现在,在每个活动中,添加以下代码以应用更改后的语言。

这是科特林代码:

override fun attachBaseContext(newBase: Context) {
    var languageType = Prefs.getString("languageType", "en", newBase).toString()
    super.attachBaseContext(MyContextWrapper.wrap(newBase, Locale(languageType, "")))
}

当您选择不同的语言时,请使用以下代码:

LanguageUtil.changeLanguageType(this@MainActivity, Locale.ENGLISH) // for englsih
LanguageUtil.changeLanguageType(this@MainActivity, Locale("es","")) // for spanish
LanguageUtil.changeLanguageType(this@MainActivity, Locale.FRENCH)// for french

之后还将其存储在共享首选项中。

请记住:如果您更改当前活动中的语言,您将不会看到语言更改,因为您需要重新启动活动才能看到更改,但在当前活动之后打开的活动您将看到更改。

如果你在同一个activity中调用recreate(),它会闪烁屏幕,所以不要使用recreate()函数。

我有一个解决方案(不是正确的解决方案,但我可以说它是补丁并且工作完美)。 为了显示当前活动中的更改,您需要在默认 strings.xml 中创建所有英语、西班牙语和法语字符串,并在用户选择不同语言时在当前活动中将其设置为运行时。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 Oreo android 更改我的应用程序的语言 的相关文章

  • 使用 process.on('uncaughtException 显示 500 错误页面

    我正在开发一个快速应用程序 我的 server js 目前有以下内容 process on uncaughtException function err console log UNCAUGHT EXCEPTION console log
  • React-Native 中的导航抽屉

    我是反应原生的新手 不介意我问一个基本问题 我想知道 实现抽屉式导航的分步过程是什么 推荐链接这个链接 https github com react native community react native side menu usage
  • 将 React Native 应用程序嵌入到现有的 ios/android 应用程序中

    我需要知道是否可以在现有的 ios android 应用程序中 嵌入 一个 React Native 应用程序 而不共享 React Native 应用程序代码 我们目前有一个 React Native 应用程序 它使用一些插件依赖项 并被
  • SDK 管理器缺少模拟器的旧版 Android 系统映像

    我刚刚重新安装了 ADT 捆绑包 20130522 和 Android Studio 因为我的 eclipse 安装再次搞砸了 但那是另一个故事了 在任一版本中 当我启动 SDK Manager 时 都没有任何 2 2 的系统映像 只有 2
  • Gradle 构建过程失败

    我的项目正在成功构建 突然我在 Android studio 中收到以下错误 无法找到方法 org gradle api publish maven internal publication MavenPublicationInternal
  • 彩信数据总是错误

    我正在从 Galaxy S6 读取短信和彩信数据 所有 SMS 消息都有一个date像这样的字段1456252633000 该数字是 unix 时间戳 1000 我发送 未收到 的彩信具有如下日期字段 1440628863时间戳是正确的 u
  • 定时器时间不作为变量改变?

    这是我的代码 private int V Time 1 try final Timer V Timer final Handler V Handler V Timer new Timer V Handler new Handler Loop
  • 移动到SD卡

    我知道从 android 2 2 开始可以使用移动到 SD 卡功能 我想知道有没有办法在我的程序中检测设备是否支持移动到 SD 卡功能 如果支持 则可以移动 否则如果不支持 则什么也不会发生 将在手机内存中 我的主要问题是我的应用程序支持
  • 如何切换状态栏?

    我正在寻找一种显示和隐藏状态栏的方法onClickListener 但仅显示其有效 WindowManager LayoutParams lp getWindow getAttributes if isStatusbarVisible lp
  • Android TextView 中的等宽表格数字

    我有一个自定义字体 默认情况下具有可变宽度数字字形 并且我想在 Android 中使用该字体的等宽表格数字功能TextView使数字垂直对齐 也就是说 改变如下 像这样的事情 要选择字体的表格数字功能 请使用TextView s fontF
  • 视图随软键盘移动,遮挡其他 UI 对象

    我有一个容器视图 我希望它始终位于视图底部 位于 ScrollView 下方 ScrollView 有一些 UI 对象 其中一个是 EditText 对象 目前 当用户点击 EditText 对象内部时 android softkeyboa
  • 如何让 Mockito 在 androidTest 中工作

    在我的测试中 我如何模拟我编写的课程 这是我的测试代码 import android support test runner AndroidJUnit4 import org junit Before import org junit Te
  • Android 中的 BLE Gatt onConnectionStateChanged 失败,状态为 257

    我正在开发一个同时连接到多个BLE设备的Android应用程序 之后我从这些设备永久读取特征 但过了一会儿 我在onConnectionStateChanged 函数中得到状态257 android文档没有解释错误的原因是什么 或者如何修复
  • 通知管理器所需的权限

    我正在尝试使用以下命令将振铃器设置为静音且请勿打扰优先级 AudioManager myAudioMgr AudioManager context getSystemService Context AUDIO SERVICE Notific
  • 谷歌地图URL中参数的含义是什么

    我正在 Android 上使用 Webkit 浏览器 我想在以下 URL 中获得一个红色 A 符号
  • 突出显示菜单抽屉/滑动菜单中的所选项目

    使用的库 https github com SimonVT android menudrawer https github com SimonVT android menudrawer https github com JakeWharto
  • 使用Gradle组装时如何更改Android应用程序包名称?

    是否可以使用 Gradle 更改 Android 应用程序的包名称 我需要编译同一应用程序的两个副本 并具有唯一的包名称 这样我就可以向市场发布两次 作为使用的更简单的替代方案产品口味 正如伊森的回答 https stackoverflow
  • 如何检查设备上是否安装了电子邮件客户端

    我需要检查设备上是否安装了电子邮件客户端 我使用了以下代码 但它对我不起作用 public boolean isIntentAvailable final PackageManager packageManager getApplicati
  • 如何获取视图到手机底部的距离?

    如果我在布局上有某个视图 ImageView 例如 是否可以找到View的下边框到手机屏幕底部的距离 Thanks instantiate DisplayMetrics DisplayMetrics dm new DisplayMetric
  • Android 可扩展列表视图随机播放子项

    你好 我正在使用 Android Expandable listview 并用不同的视图在其中膨胀子视图 我遇到的问题是 当我展开视图然后打开另一个父视图时 布局中的子视图会变得混乱并在代码中膨胀错误的布局 这是我的两个项目的示例代码 这是

随机推荐

  • Pytesseract:“TesseractNotFound 错误:tesseract 未安装或不在您的路径中”,如何解决此问题?

    我正在尝试在 python 中运行一个基本且非常简单的代码 from PIL import Image import pytesseract im Image open sample1 jpg text pytesseract image
  • Powershell - 获取 ADComputer -properties 成员

    我试图查找我们环境中是否有任何服务器尚未应用于特定组 我有一个组列表 我们使用这些组在特定的白天 晚上 手动等修补我们的 Windows 服务器 我正在尝试检查我们环境中的任何服务器是否错误地放置在域中并错过了此步骤 没有有一个补丁组成员
  • java.lang.OutOfMemoryError:启动时Java堆空间

    前几天我开始遇到一个java lang OutOfMemoryError Java heap spaceMATLAB 启动时出现异常 在运行任何代码或向路径添加任何内容之前 MATLAB 加载的默认目录中也没有文件 我在 Windows 7
  • 在 C# 中使用 Microsoft Graph API 获取所有电子邮件

    我有以下函数来使用 Graph API 获取消息 var client new GraphServiceClient authenticationProvider var messages await client Users use em
  • 找不到中间过滤器的组合

    我正在使用 Visual Studio 制作一个 Windows 窗体应用程序 该应用程序允许您输入照片的名称 然后将该图像保存到网络上的特定位置 当我在笔记本电脑上使用它时 效果非常好 但是 当我尝试在桌面上运行它时 它不起作用 相反 我
  • 定义结构时避免“重新定义 typedef”警告

    我定义了一些相互引用的结构 并在使用它们之前对结构进行类型定义 因此每个结构都 了解 其他结构 如果没有这个 就会出现编译错误 不确定这是否必要或正确 现在 当使用 gcc 编译时 我收到 redefinition of typedef 警
  • Javascript - 将字符串中的所有数字更改为下标

    我有一个输入框 用户在其中输入化学式 我将他们的输入显示在表格中 并在我的 javascript 文件中包含以下代码 document getElementById entered innerHTML userIn 其中 userIn 是输
  • 如何执行逐像素匹配来检查模板数据库中是否存在查询图像[重复]

    这个问题在这里已经有答案了 我正在研究手背静脉识别系统 我已经对图像进行了二值化和预处理 然后对细化的静脉图案进行特征提取 白色像素坐标 如下图 图 1 所示 对 10 个图像重复这些步骤 并将它们的坐标存储在 txt 文件中 现在 假设我
  • 如何使用 sendAsynchronousRequest:queue:completionHandler:

    两部分问题 第一部分 我正在尝试向我的数据库创建异步请求 我目前正在同步进行 但是我想学习这两种方法 以更好地理解正在发生的事情 目前我已经像这样设置了同步调用 IBAction setRequestString NSString stri
  • 在 .NET 中存储数据的方法

    我正在寻找在 NET 中的 Windows 窗体应用程序中存储数据的方法 我想让系统的输入数据持久化 因此当我关闭程序并再次打开它时 会检索数据 除了创建链接数据库之外 还有哪些方法可以实现此目的 我们很高兴地赞赏这些例子 有数十种不同的方
  • 尝试安装 HAXM 时出错 - Intel VT-x 已关闭

    我已经安装了 Android Studio 但在尝试安装 HAXM 时收到此错误 我尝试在BIOS中启用虚拟化 但并没有解决问题 然后我在 Windows 8 1 64 位 中禁用了 Hyper V 重新启动计算机后 没有任何变化 并且由于
  • 融合类型中的 C++ 类

    我希望为一堆 C 类实现 python 包装器 在 pxd 的某个地方我有 cdef cppclass FooImpl1 FooImpl1 int foo cdef cppclass FooImpl2 FooImpl2 int foo 我想
  • 在 EL 表达式中使用多个布尔条件

    我想知道如何在 EL 中组合多个布尔条件 我有以下示例 但它不起作用
  • 使用 JNI 访问我的共享库时出现“未定义的引用”

    我正在尝试构建一个版本Botan 加密算法库 使用 JNI 在 Android 上运行一些本机 C 程序 我已经使用 NDK 工具链 NDK R5b 成功创建了 libbotan so 没有任何错误 但是 当我从 Android 项目 示例
  • Select2 - 搜索通配符匹配项

    我正在使用 Select2 来设计我的选择框并添加功能 我想知道如何使搜索规则更加宽松 目前 如果我在下拉列表中有 新墨西哥 我可以搜索 墨西哥 或 新墨西哥 来匹配选择选项 但如果我输入 墨西哥新 我会得到 找不到结果 有没有办法扩展搜索
  • 使用 Meteor 动态加载每个模板的 JS/CSS

    我理解几个问题 即this 这种性质已经发布 但尚未找到可靠的解决方案 从表面上看 Meteor 目前缺乏动态加载 渲染不同 UI JavaScript 的能力 即uilang 或每个模板的 CSS 文件 在我的应用程序中 我的模板需要特定
  • Visual Studio 2005 和 .Net 框架 1.1

    是否可以使用 Visual Studio 2005 创建和维护 Net Framework 1 1 应用程序 实际上有一个 MSBuild 扩展允许这种情况 它被称为MSBee您可以在 CodePlex 上找到它 MSBuild Extra
  • Java和无符号字节[重复]

    这个问题在这里已经有答案了 我需要使用无符号字节数组 我需要通过网络将某些字符发送到服务器 其中一些字符大于 127 我有下面代码的简化版本来尝试理解这个概念 int i 160 byte j byte i System out print
  • 如何在VB中从数组元素中得出所有可能的总和组合

    如果有一个数组 其中元素为 1 2 3 4 则程序应返回另一个数组 其中包含所有组合的总和 1 2 3 4 3 1 2 4 1 3 5 1 4 5 2 3 6 2 4 7 3 4 6 1 2 3 7 1 2 4 8 1 3 4 9 2 3
  • 无法使用 Oreo android 更改我的应用程序的语言

    EDIT 我使用了区域设置更改的解决方案来更改应用程序的语言 但它在奥利奥中不起作用 它在我的三星 S4 上运行良好 但在我的 S9 上运行不佳 所以我正在像这样进行区域设置更改 public void initAppLanguages C