Android проблема с применением языка программно в Kotlin - PullRequest
1 голос
/ 26 января 2020

Я делал язык приложения доступным для пользователей. Итак, я добавил настройку языка в свое приложение. Я добавил счетчик на экран конфигурации, и у счетчика есть список языков (Авто, Английский sh, Китайский и др. c). Я сохраняю позицию выбранного элемента в общих настройках (значение по умолчанию 0, что Авто). В каждом классе деятельности я добавляю метод переопределения attachBaseContext (newBase: Context) . Этот код позволяет переопределить attachBaseContext

override fun attachBaseContext(newBase: Context) {
    val shared = newBase.getSharedPreferences("configuration",Context.MODE_PRIVATE)
    val position = shared?.getInt("Language",0) ?: 0

    super.attachBaseContext(LocaleManager.langChange(newBase,position)

, и это LocaleManager

object LocaleManager {
    fun langChange(context: Context, position: Int): ContextWrapper {
        var lang: String = if(position < StaticStore.lang.size)
            StaticStore.lang[position]
        else
            StaticStore.lang[0]

        if(lang == "")
            lang = Resources.getSystem().configuration.locales.get(0).language

        val config = context.resources.configuration

        if(lang != "") {
            val loc = Locale(lang)

            Locale.setDefault(loc)
            config.setLocale(loc)

            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                setSystemLocale(config,loc)
            } else {
                setSystemLocaleLegacy(config,loc)
            }
        }

        var c = context

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            c = context.createConfigurationContext(config)
        } else {
            context.resources.updateConfiguration(config,context.resources.displayMetrics)
        }

        return ContextWrapper(c)
    }

    private fun setSystemLocaleLegacy(config: Configuration, loc: Locale) {
        config.locale = loc
    }

    @TargetApi(Build.VERSION_CODES.N)
    fun setSystemLocale(config: Configuration, loc: Locale) {
        config.setLocale(loc)
    }
}

StaticStore - это класс java, в котором хранятся переменные stati c. В StaticStore

public static String[] lang = {"","en","zh","ja"};

Этот способ работал нормально, когда я использовал Java. Я думал, что преобразование моего Android проекта в Kotlin будет хорошим, поэтому я сначала преобразовал классы деятельности. Но по какой-то причине этот способ сейчас не работает.

Я искал эту проблему часами. Пробовал эти ответы и не работал

{ ссылка } (Устанавливает локаль в классе, который расширяется Приложение )

{ ссылка } (Это похоже на мой код, но он использует LocaleList , а не Locale )

Но, к счастью, я попробовал этот способ, и он наконец заработал

override fun attachBaseContext(newBase: Context) {
    val shared = newBase.getSharedPreferences(StaticStore.CONFIG, Context.MODE_PRIVATE)
    val lang = shared?.getInt("Language",0) ?: 0

    val config = Configuration() //Create new Configuration
    var language = StaticStore.lang[lang]

    if(language == "")
        language = Resources.getSystem().configuration.locales.get(0).toString()

    config.setLocale(Locale(language))
    applyOverrideConfiguration(config) //Manually override configuration using "config"

    super.attachBaseContext(LocaleManager.langChange(newBase,shared?.getInt("Language",0) ?: 0))
}

При открытии не выдает никаких ошибок, если указать c активность в первый раз . При повторном открытии того же действия (например, go возврат на главный экран и повторный вход на экран конфигурации) печатается ошибка

2020-01-26 11:26:55.619 28216-28216/com.mandarin.myapp E/AppCompatDelegate: updateForNightMode. Calling applyOverrideConfiguration() failed with an exception. Will fall back to using Resources.updateConfiguration()
java.lang.IllegalStateException: Override configuration has already been set
    at android.view.ContextThemeWrapper.applyOverrideConfiguration(ContextThemeWrapper.java:99)
    at androidx.appcompat.app.AppCompatDelegateImpl.updateForNightMode(AppCompatDelegateImpl.java:2281)
    at androidx.appcompat.app.AppCompatDelegateImpl.applyDayNight(AppCompatDelegateImpl.java:2170)
    at androidx.appcompat.app.AppCompatDelegateImpl.attachBaseContext(AppCompatDelegateImpl.java:334)
    at androidx.appcompat.app.AppCompatActivity.attachBaseContext(AppCompatActivity.java:98)
    at com.mandarin.myapp.ConfigScreen.attachBaseContext(ConfigScreen.kt:371)
    at android.app.Activity.attach(Activity.java:6598)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2580)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6077)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)

Я понимаю эту ошибку, но мне приходится использовать applyOverrideConfiguration (config) для решения проблемы настройки локали. Странно то, что, хотя эта ошибка печатается, приложение не взломает sh, но меня это сильно беспокоит.

В любом случае, из-за этой ошибки я попытался использовать applyOverrideConfiguration (config) только один раз, используя stati c boolean. Это может изменить язык хорошо, когда я открываю деятельность в первый раз. Но когда я снова открываю ту же активность, она снова показывает язык по умолчанию (Engli sh - это язык устройства). Таким образом, это означает, что только applyOverrideConfiguration (config) может изменить язык ...

На самом деле мне не нужно вызывать этот метод, когда super.attachBaseContext (LocaleManager.langChange (newBase) , position) работает нормально, но по какой-то причине не работает.

Есть ли способы использовать applyOverrideConfiguration без ошибок печати? Или есть способы решить проблему изменения языка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...