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