4

I've read everything about in-app language changing at runtime. Everything currently works correctly for API 26+27+28+29 (yes, I've tested all of them) and start breaking at API 25 and below. Now the only thing I know that happened in API level 26 was that application and activities no longer share the same resources (aka the top level resources) by default. And also that updateConfiguration for Resources gets deprecated in favor of createConfigurationContext in API 25

However that gives me zero clues really.

Here is my code:

public class BaseApp extends MultiDexApplication { //for MinSDK < 21, otherwise "extends Application"

@Override
public void onCreate() {
    LocaleHelper.updateResources(this);
    super.onCreate();
}

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(LocaleHelper.updateResources(base));
    MultiDex.install(this); /* Needed as per (@link MultiDexApplication) */

}

@Override
public void onConfigurationChanged(Configuration config) {
    super.onConfigurationChanged(config);
    LocaleHelper.updateResources(this);
}

Base Activity:

public abstract class BaseActivity extends AppCompatActivity {

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(LocaleHelper.updateResources(base));
}

Helper class:

class LocaleHelper {

static Context updateResources(Context context) {
    Resources resources = context.getResources();
    Configuration config = new Configuration(resources.getConfiguration());
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
    String lang = preferences.getString(Constants.PREF_KEY_LOCALE_OVERRIDE, Constants.PREF_VALUE_LOCALE_SYSTEM);
    Locale locale = new Locale(lang);

    if (Build.VERSION.SDK_INT >= 17) {
        config.setLocale(locale);
        context = context.createConfigurationContext(config);
    } else {
        config.locale = locale;
        resources.updateConfiguration(config, resources.getDisplayMetrics());
    }
    return context;
}
PIXP
  • 2,382
  • 3
  • 19
  • 28

3 Answers3

1

It is a kwown bug fo the AppCompat implementation of AndroidX. The bug is in the version 1.0.0: 'androidx.appcompat:appcompat:1.1.0' I confirm it works in the version 1.2.0 of the library.

Christian
  • 437
  • 1
  • 4
  • 13
0

try this :

 private Context updateResources(Context context, String language) {
    Locale locale = new Locale(language);
    Locale.setDefault(locale);

    Resources res = context.getResources();
    Configuration config = new Configuration(res.getConfiguration());
    if (Utility.isAtLeastVersion(N)) {
        setLocaleForApi24(config, locale);
        context = context.createConfigurationContext(config);
    } else if (Utility.isAtLeastVersion(JELLY_BEAN_MR1)) {
        config.setLocale(locale);
        context = context.createConfigurationContext(config);
    } else {
        config.locale = locale;
        res.updateConfiguration(config, res.getDisplayMetrics());
    }
    return context;
}

@RequiresApi(api = N)
private void setLocaleForApi24(Configuration config, Locale target) {
    Set<Locale> set = new LinkedHashSet<>();
    // bring the target locale to the front of the list
    set.add(target);

    LocaleList all = LocaleList.getDefault();
    for (int i = 0; i < all.size(); i++) {
        // append other locales supported by the user
        set.add(all.get(i));
    }

    Locale[] locales = set.toArray(new Locale[0]);
    config.setLocales(new LocaleList(locales));
}

and also check this article : https://proandroiddev.com/change-language-programmatically-at-runtime-on-android-5e6bc15c758

0

Why don't you use https://github.com/YarikSOffice/lingver library.

In addition to that library, I also have to add this line in order to restart my settings activity.

UtilLanguage.setLanguage(activity, position); //This is the line where I used library   
activity.recreate();

Also for the previous activity (Backstack of the Settings activity), I stored existing language and check the changes on resume method in order to update my main activity;

@Override
public void onResume() {

    if (selectedLanguageIndex != appPreferences.getPreferredApplicationLanguageIndex()) {
        recreate();
    }
}
Berkay Turancı
  • 3,373
  • 4
  • 32
  • 45