无法使用 Oreo android 更改我的应用程序的语言 [英] Can't change the language of my app with Oreo android

查看:19
本文介绍了无法使用 Oreo android 更改我的应用程序的语言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(编辑)

我使用了语言环境更改解决方案来更改我的应用程序的语言,但它在 oreo 中不起作用.它在我的三星 S4 上完美运行,但在我的 S9 上却没有.

I used a solution for locale change to change the language of my app and it is not working in oreo. It's working perfectly on my samsung S4, but not on my 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);

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

What am I doing wrong? Why is it not working in Oreo?

推荐答案

请按照以下步骤操作:

注意:我假设您在 values 文件夹中为不同的英语、西班牙语和法语创建了不同的字符串文件.(即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 类文件)注意:您可以使用自己的首选项创建和检索代码.

Now Create Prefs file: Prefs.kt (This is Kotlin class file) Note: You can use your own preference creation and retrivation code.

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

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

Now create one class TestApp which extends the Application class. This will use to save the last selected language you want to apply when app restarts. Note: don't forget to add this app class name "TestApp" to AndroidManifest.xml in tag.

添加文件:TestApp.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)
    }

}
}

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

Now in each activity, add the code below to apply the changed language.

这是 Kotlin 代码:

This is Kotlin code:

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

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

When you select the different language, use this code:

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

之后也将其存储在 sharedpreference 中.

and after also store it in sharedpreference.

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

Remember: If you change language in current Activity and you will not see the language change in that, because you need to restart activity to see the changes but activity opened after this current activity you will see the changes.

如果您在同一个活动中调用 recreate(),它会闪烁屏幕,所以不要使用 recreate() 函数.

If you call recreate() in the same activity, it will blink the screen, so do not use the recreate() function.

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

I have one solution (not proper solution but I can say it is patch and it is worked perfect). For displaying changes in current activity you need to create all the english, spanish and french string in default strings.xml and set it runtime in current activity when the user selects a different language.

这篇关于无法使用 Oreo android 更改我的应用程序的语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆