onConfigurationChanged is not being called on language change - android

Although I added to the manifest file, for each activity,
android:configChanges="locale|layoutDirection"
the method is not being called, when I change the language inside the application.
Code to change the langauge
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
// Configuration: a class describing all device configration information that can impact resources the apllication retrieves.
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
I know it is not called because I am printing to logcat and displaying a message and none is being executed
#Override
public void onConfigurationChanged (Configuration newConfig){
printMyLogCat("in Onconfigarion changed");
doMyToast(this, "in Onconfigarion changed");
super.onConfigurationChanged(newConfig);
}
public void printMyLogCat(String string) {
Log.i(getClass().getName(), string);
}
public void doMyToast(Context context, String string){
Toast.makeText(context, string, Toast.LENGTH_SHORT).show();
}

Related

Android Locale Changed but translated strings not coming in the app

Following is the Application code of my Android app:
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString(getString(R.string.pref_language), "");
if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Log.i("Locale" , lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}
I have got to change the value of settings.getString(getString(R.string.pref_language), ""); from the Settings Activity of my app.
The problem is none of the strings (which have a translation) and are accessed using getString() method, are showing the translated text.
EDIT1 : I am using Android 8.0
In android 8, the behavior of the Locales changed, now every Activity context will take its locale, i.e if you in Activity1 and changed the locale for Activity1, then Activity2 will remain on the default locale.
The solution is to change the locale for every Activity and your issue will be fixed.
When you are using getString(R.string.pref_language) the call will return the string from the language matching Locale.getDefault() as long as a translation is provided.
If a translation is not provided it will return the default language, that is the language your using in the values/strings.xml file.
All translated values are in values-xx folders, where xx is the 2 letter ISO code for the language.

Google Map Caching Issue

I am working with google map in my activity.
When i change language for example Chinese in my app settings
the langauge of map did not change till i reopen my app.
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
setContentView(R.layout.activity_maps);
i searched a lot about this issue i found that it is google map caching issue but did not found any solution.
I can think about 2 options to solve this:
Calling setContentView in the onConfigurationChanged method
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (language_changed){//pseudo_code
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
setContentView(R.layout.activity_maps);
//now you need to do again all the findViewById call
}
}
Restart the activity in the onConfigurationChanged method
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (language_changed){//pseudo_code
startActivity(CurrentActivity.this, CurrentActivity.class);
finish();
}
}
I've not tested this, but maybe it's a starting point to try to solve your problem.
Don't forget to add android:configChanges="locale" to your activity tag in the AndroidManifest.xml to let the system know that you want to handle Locale changes by yourself. Read more here if needed
You can use BroadcastReceiver with LOCALE_CHANGED Intent to detect setting change, and then update your view (Map view or total layout).
https://developer.android.com/reference/android/content/Intent.html#ACTION_LOCALE_CHANGED
public class LocaleReceiver extends BroadcastReceiver {
public LocaleReceiver() {}
#Override
public void onReceive(Context context, Intent intent) {
if(Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())){
// Call a method to trigger view refreshing here
}
}
}

How to Refresh App with onConfigChanges without loosing instance

protected void onResume() {
super.onResume();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString("lang_list", "");
// Log.d("Lang",lang);
if (!"".equals(lang) && !config.locale.getLanguage().equals(lang)) {
recreate();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
if (AppController.getInstance().isPreferenceChanged()) {
setupViewPager(viewPager);
adapter.notifyDataSetChanged();
}
}
I want to change the app language without recreate the app. I mean I want to do it when user select any language from the setting then it Should change the Setting Activity language without using recreate();, because when I use recreate(); it blinks the App once.
So I am not using recreate();. Instead I wrote below code in Setting Activity in AndroidManifest.xml
<activity
android:name=".activity.SettingsActivity"
android:label="#string/title_activity_settings"
android:configChanges="orientation|keyboardHidden|screenSize|locale|layoutDirection"/>
As in below screenshot you can see that I have selected "Hindi" for the language but it is not updating the Activity to Hindi. I mean "Select Country", "Select Your Language" and "Select Categories" should be display in Hindi instead of English. I have wrote String in both languages.
Can Anybody know How to change it when Change the language ?
OR
Why onConfigChanges is not working for locale as it is working for Orientation.
Thank you !
In your MainActivity call sharedPrefrences on onStart callback insted of calling in onCreate
Example:-
protected void onStart() {
SharedPreferences sharedPreferences = this.getSharedPreferences("selectedLanguage", Context.MODE_PRIVATE);
String pine = sharedPreferences.getString("language", DEFAULT);
String languageToLoad = pine;
Locale locale = new Locale(languageToLoad);//Set Selected Locale
Locale.setDefault(locale);//set new locale as default
Configuration config = new Configuration();//get Configuration
config.locale = locale;//set config locale as selected locale
this.getResources().updateConfiguration(config, this.getResources().getDisplayMetrics());
invalidateOptionsMenu(); //This changes language in OptionsMenu too
setTitle(R.string.app_name); //calling app name according to language selected by user
super.onStart();
}
You can use a singleton class that will handle the language change without restarting the activity,
public class MyApplication extends Application
{
private Locale locale = null;
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (locale != null)
{
newConfig.locale = locale;
Locale.setDefault(locale);
getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics());
}
}
#Override
public void onCreate()
{
super.onCreate();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Configuration config = getBaseContext().getResources().getConfiguration();
String lang = settings.getString(getString(R.string.pref_locale), "");
if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang))
{
locale = new Locale(lang);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
}
}
}

How to reload the current view when I change the locale in app in android

I am currently work with changing language in the app. My app structure is tab host + fragment I have successfully change the locale but it is quite strange.
That means after I run the change locale code , it does not change the view immediately but only when I go to another tab. I think this is due to I need to reload the view, but are there any way to implment this without kill and restart the activity?
Because there is some goolge analytic code, the entry number will be increase if the user start activity again? Are there standard way to reload view? thanks
The change locale function is in one of the tabhost fragment, I have to refresh the view in tabhost (main activity), and the current fragment .
public OnClickListener setChangeLangListener(final String lang) {
OnClickListener changeLangListener = new OnClickListener() {
#Override
public void onClick(View arg0) {
Configuration config = new Configuration(getResources()
.getConfiguration());
if (lang.equals("en")) {
config.locale = Locale.ENGLISH;
chi.setTextColor(oldColor);
eng.setTextColor(getActivity().getResources().getColor(android.R.color.white));
} else {
config.locale = Locale.TRADITIONAL_CHINESE;
eng.setTextColor(oldColor);
chi.setTextColor(getActivity().getResources().getColor(android.R.color.white));
}
getResources().updateConfiguration(config,
getResources().getDisplayMetrics());
}
};
return changeLangListener;
}
eng.setOnClickListener(setChangeLangListener("en"));
chi.setOnClickListener(setChangeLangListener("zh"));
Allright add this to your manifest
android:configChanges="locale"
and override onConfigurationChanged() in your activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
// refresh your views here
super.onConfigurationChanged(newConfig);
}
go here for more info.
Hope it helps. :)
Have you tried calling setContentView. Eg.:
String languageToLoad = "fr"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
activity.setContentView(R.layout.your_layout);

Change the locale at runtime?

We have an Android app that functions as a client for a remote PC program. We'd like to add a feature so the PC can instruct the Android app to change its locale at runtime, i.e., start the app; put it in communication with the PC; sometime later the PC tells the app to switch to, say, Spanish or Chinese.
We already have all the layout and string resources set up for their respective locales. Our app is the only app the user sees so it doesn't matter if the rest of the device stays in English.
There is another thread on this at Change language programmatically in Android but it doesn't seem to reach a conclusion.
I can put . . .
Locale locale = new Locale(sTheNewLocale);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
. . . in onCreate() before the setContentView() but that doesn't really help if I want to change the locale after my screen is up and running. Is there a way to REload the content view after the Activity is already running? So is there any practical way to change locales on-the-fly reliably or do I have to tell my boss it can't be done except for setting the whole device to the new locale before starting the app?
Since API 11 you can use recreate so can make this method in your activity:
private void restartInLocale(Locale locale)
{
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
Resources resources = getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());
recreate();
}
You can start a new instance of your activity and exit the old one. Here is a full (untested) example how you can store any desired language and restart your app. You just need to call restartInLanguage with your prefered language.
public class YourMainActivity extends Activity {
private static final String APP_SHARED_PREFS = "com.example.test";
private SharedPreferences settings;
private Editor editor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings=getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
editor=settings.edit();
Locale locale = new Locale(settings.getString("lang", "default-lang"));
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
// your stuff...
}
public void restartInLanguage(String lang) {
editor.putString("lang", lang);
editor.commit();
Intent intent = getIntent();
finish();
startActivity(intent);
}
// ...
}
I have combined #weston and #rekire (both +1) and extendet it to handle this use-case:
ActivityA => ActivityB => SettingsActivity-changeLocale
After changeLocale in SettingsActivity the parent activities ActivityA and ActivityB should also be recreated to reflect the new locale.
My solution: ActivityA and ActivityB inherit from LocalizedActivity which checks in onResume if the locale has changed and trigger a recreate() if necessary
So every activity that inherits from LocalizedActivity automatically handles app specific locale change.
/**
* An activity that can change the locale (language) of its content.
*
* Inspired by http://stackoverflow.com/questions/13181847/change-the-locale-at-runtime
*
* Created by k3b on 07.01.2016.
*/
public class LocalizedActivity extends Activity {
/** if myLocale != Locale.Default : activity must be recreated in on resume */
private Locale myLocale = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
fixLocale(this);
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
// Locale has changed by other Activity ?
if ((myLocale != null) && (myLocale.getLanguage() != Locale.getDefault().getLanguage())) {
myLocale = null;
recreate();
}
}
/**
* Set Activity-s locale to SharedPreferences-setting.
* Must be called before onCreate
* #param context
*/
public static void fixLocale(Context context)
{
final SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
String language = prefs.getString(Global.PREF_KEY_USER_LOCALE, "");
Locale locale = Global.systemLocale; // in case that setting=="use android-locale"
if ((language != null) && (!language.isEmpty())) {
locale = new Locale(language); // overwrite "use android-locale"
}
if (locale != null) {
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
Resources resources = context.getResources();
resources.updateConfiguration(config, resources.getDisplayMetrics());
// recreate();
if (context instanceof LocalizedActivity) {
((LocalizedActivity) context).myLocale = locale;
}
}
}
}
Here is the source of LocalizedActivity.java and SettingsActivity.java that are used in my A Photo Manager project
The solution is to use setContentView and controlLanguage (you can also call this method from a Global class) methods in EVERY activity in onResume method after setting your locale.
Example:
#Override
public void onClick(View v) {
SharedPreferences.Editor editor;
editor = sharedPref.edit();
Configuration config = new Configuration(getBaseContext().getResources().getConfiguration());
String language = "";
switch (v.getId()){
case R.id.turkceButton:
editor.putString("language", "tr");
language="tr";
break;
case R.id.englishButton:
editor.putString("language", "en");
language="en";
break;
}
Locale locale = new Locale(language);
Locale.setDefault(locale);
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
editor.commit();
#Override
protected void onResume() {
super.onResume();
controlLanguage(getApplicationContext(), getResources());
setContentView(R.layout.main);
}
public void controlLanguage(Context context, Resources res){
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
String language = sharedPref.getString("language","en");
Locale locale = new Locale(language);
Locale.setDefault(locale);
res.getConfiguration().locale = locale;
res.updateConfiguration(res.getConfiguration(), res.getDisplayMetrics());
}

Categories

Resources