24

The link of the latest app-compat which is 1.1.0.

After upgrading my app to the latest app-compat my language settings stopped working for phones below API 24 (roughly, doesn't work on API 21 and below for sure).

For API 24 and above, I have used the ContextWrapper and set the locale hence works.

My question is if the androidx.appcompat:appcompat:1.1.0is the stable version why does it work for me in alpha and beta versions unlike the others here & the questions which I have tried.

Should I wait for an official stable version again and downgrade to the last stable version or which is the efficient way to let google know if any(ofcourse, I know to file a bug)?

sanjeev
  • 1,664
  • 19
  • 35
  • 1
    Yes, this may be a bug. If you really don't need version `1.1.0` then downgrade and wait for the stable version release – Rahul Khurana Sep 12 '19 at 06:08
  • 1
    @RahulKhurana right. Thanks mate. Will do that. – sanjeev Sep 12 '19 at 06:15
  • @0101100101 You got it wrong.. I have mentioned that link already and the latest `1.1.0` has come.. it does work for me on alpha and beta versions, but not on the latest version 1.1.0 after that. – sanjeev Sep 19 '19 at 06:44
  • yep you're right, the question is different, but in any case I added a fix in the linked question you might find useful – 0101100101 Sep 19 '19 at 06:48

4 Answers4

31

Edit:

To continue using version 1.1.0 add this below your attachBaseContext:

Kotlin solution:

override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
    if (overrideConfiguration != null) {
        val uiMode = overrideConfiguration.uiMode
        overrideConfiguration.setTo(baseContext.resources.configuration)
        overrideConfiguration.uiMode = uiMode
    }
    super.applyOverrideConfiguration(overrideConfiguration)
}

Java solution:

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
    if (overrideConfiguration != null) {
        int uiMode = overrideConfiguration.uiMode;
        overrideConfiguration.setTo(getBaseContext().getResources().getConfiguration());
        overrideConfiguration.uiMode = uiMode;
    }
    super.applyOverrideConfiguration(overrideConfiguration);
}

If you don't need to upgrade to the latest appCompat then check the old answer. Else use the solution provided by @0101100101 here.

Old Answer:

After spending hours trying, got to know that it might be a bug.

Downgrade to the last stable version and it works flawlessly.

dependencies {
    implementation 'androidx.appcompat:appcompat:1.0.2'   //************ DO NOT UPGRADE LANGUAGE ISSUE on API 23 and below *******************//
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
....
}

Meanwhile, I have filed an issue with Google https://issuetracker.google.com/issues/140880275

sanjeev
  • 1,664
  • 19
  • 35
  • 2
    This is sick what's happening to Google libs quality. I was struggling with that for hour too. – Szymon Klimaszewski Sep 15 '19 at 09:26
  • 2
    This stopped working after `1.2.0-alpha02` for Android 6.0.1 API 23, even though they said it's fixed in https://issuetracker.google.com/issues/140602653 :/ – Aba Mar 08 '20 at 04:29
  • i updated to androidx.appcompat:appcompat:1.2.0 and the applyOverrideConfiguration is not called anymore which is causing an issue again – Rashad.Z Aug 18 '20 at 10:52
  • @Rashad.Z I think this issue must be fixed in the latest appcompat version. – sanjeev Aug 20 '20 at 05:29
7

There is an issue in new app compat libraries related to night mode that is causing to override the configuration on android 21 to 25. This can be fixed by applying your configuration when this public function is called:

public void applyOverrideConfiguration(Configuration overrideConfiguration

For me, this little trick has worked by copying the settings from the overridden configuration to my configuration but you can do whatever you want. It is better to reapply your language logic to the new configuration to minimize errors

@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT <= 25) {
        //Use you logic to update overrideConfiguration locale
        Locale locale = getLocale();//your own implementation here
        overrideConfiguration.setLocale(locale);
}
super.applyOverrideConfiguration(overrideConfiguration);
}
Jack Lebbos
  • 237
  • 3
  • 10
  • doesn't help, because this code change makes all plural strings crash with `java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.icu.util.ULocale.getBaseName()' on a null object reference at android.icu.impl.PluralRulesLoader.getRulesIdForLocale(PluralRulesLoader.java:166)` – 0101100101 Sep 19 '19 at 04:25
  • This is the function responsible for the issue. The configuration is overridden from android 21 to android 25 because of a night mode bug. You can implement any logic you want as long as it is applied before the `super.applyOverrideConfiguration` is called. Also, you can add checking if the android version is between 21 and 25. @sanjeev @ 0101100101 – Jack Lebbos Sep 19 '19 at 06:23
  • Doesn't work. I crashes with log: java.lang.IllegalStateException: getResources() or getAssets() has already been called at android.view.ContextThemeWrapper.applyOverrideConfiguration(ContextThemeWrapper.java:95) – Shayan_Aryan Nov 01 '19 at 12:58
2

To work well locale change with the latest appcompat v1.2.0 use the below code.

(1) Add this function to your base activity.

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(setDefaultLanguage(newBase)); // Selected app language.
    applyOverrideConfiguration(newBase.getResources().getConfiguration());
}

Note: Do not override this method "applyOverrideConfiguration" in your activity.

Faldu Jaldeep
  • 545
  • 2
  • 15
-2

Android x has supported this type of library ...

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation "com.google.android.material:material:1.1.0-alpha09"

}

Please always change androidx in design library or other som default android library.

And the compulsory change in layout code similar as ...

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_views"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:clipToPadding="false"
            android:padding="2dp" />


<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

so more other some type code change in layout...