i have to implement an app prototype that should have the possibility to change the language inside the app.
My code:
...builder.setItems(langList, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
selectedLanguage = which;
if (selectedLanguage != -1) {
Configuration configuration = new Configuration(getResources().getConfiguration());
String currentLanguage = configuration.locale.getLanguage();
switch (selectedLanguage) {
case 0:
if (currentLanguage.equalsIgnoreCase("de")) {
configuration.locale = Locale.ENGLISH;
} else {
return;
}
break;
case 1:
if (currentLanguage.equalsIgnoreCase("en")) {
configuration.locale = Locale.GERMAN;
} else {
return;
}
break;
default:
break;
}
getResources().updateConfiguration(configuration, null);
Intent intent = new Intent(getActivity(), DashboardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
dialog.dismiss();
}...
and it works nice. But the problem is - as you change the display mode (portrait <=> landscape) loads the current system language (respectively strings.xml in values folder) again.
has anyone already experience with it, or maybe a suggestion how could I solve this problem?
thanks in advance..
you can when the user select its language save it in preferences and in oncreate method check if preferences have value for language or not if not load the default language
by default the change orientation will call the oncreate method so fell free to add checking code in it
You can know problematically when the orientation change happens because the onConfigurationChanged() lifecycle event happens.
See the following example for how you can detect the orientation change. http://techblogon.com/android-screen-orientation-change-rotation-example/
When the configuration changes you can store any values you need. Please note that you can also store the values in a setting when they are first set.
When creating the activity (onCreate()) you can read the orientation and set any appropriate values.
In summary, review the Activity lifecycle, there are relevant events there you can trigger on.
so, I solved the problem using SharedPreferences:
... default:
break;
}
SharedPreferences preferences = getActivity().getSharedPreferences("SETTINGS_FILE", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("currentLanguage", configuration.locale.getLanguage());
editor.commit();
getResources().updateConfiguration(configuration, null); ...
then I implemented method setCurrentLanguage() in my MainActivity/MainFragment:
... protected void setCurrentLanguage() {
Configuration configuration = new Configuration(getResources().getConfiguration());
SharedPreferences preferences = getSharedPreferences("SETTINGS_FILE", Context.MODE_PRIVATE);
String restoredLanguage = preferences.getString("currentLanguage", null);
if (restoredLanguage.equalsIgnoreCase("en")) {
configuration.locale = Locale.ENGLISH;
getResources().updateConfiguration(configuration, null);
}
} ...
and finnaly i call this method in every activity/fragment before setContentView(...):
// in an activity
... protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCurrentLanguage();
setContentView(R.layout.activity_dashboard); ...
// or in a fragment
... public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setCurrentLanguage();
View rootView = inflater.inflate(R.layout.fragment_preferences,
container, false); ...
Thanks again for your help ;)
Related
MyApp testing is multi language change. http://www.androhub.com/android-building-multi-language-supported-app/ After I choose radio button, it changes language in current activity. But when I go back previous activity, it doesn't change language. So, I want to recall onCreate when I click back button. Or How to refresh current activity?
onCreate ()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
txt = (TextView) findViewById(R.id.txt);
radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
radioEng = (RadioButton) findViewById(R.id.eng);
radiohi = (RadioButton) findViewById(R.id.hi);
// Initialization
pref = getSharedPreferences("MyPref", Activity.MODE_PRIVATE);
editor = pref.edit();
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, #IdRes int i) {
String lang = "en"; // Default Language
switch (i) {
case R.id.eng:
lang = "en";
break;
case R.id.hi:
lang = "hi";
break;
default:
break;
}
changeLocale(lang); // Change Locale on selection basis
}
});
loadLocale();
}
changeLocale
private void changeLocale(String lang) {
if (lang.equalsIgnoreCase(""))
return;
Locale myLocale = new Locale(lang); // Set Selected Locale
saveLocale(lang); // Save the selected locale
Locale.setDefault(myLocale); // set new locale as default
Configuration config = new Configuration(); // get Configuration
config.locale = myLocale; // set config locale as selected locale
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); // Update the config
}
saveLocale & loadLocale
private void saveLocale(String lang) {
editor.putString("save", lang);
editor.commit();
if (lang.equals("en")) {
radioEng.setChecked(true);
} else {
radiohi.setChecked(true);
}
}
private void loadLocale() {
String lang = pref.getString("save", "");
if (lang.equals("")) {
radioEng.setChecked(true);
} else {
changeLocale(lang);
}
}
give resultCode when back from current activity, or save configuration, then check configuration on activity resume for language change
I think you should finish the previous activity and recreate it, you can use LocalBroadcast.
You can call onCreate method on back press by handling back press event.
#Override
public void onBackPressed() {
onCreate(new Bundle());
}
If you are using API 11 then use below code and also if above code doesn't work.
Intent intent = getIntent();
finish();
startActivity(intent);
While using the recreate method works by doing
this.recreate()
It was only added in API level 11. If you want to include more devices you can check the API level and implement both the recreate method as well as
Intent intent = getIntent();
finish();
startActivity(intent);
You can use both by making an if statement like...
if (android.os.Build.VERSION.SDK_INT >= 11){
//Code for recreate
recreate();
}else{
//Code for Intent
Intent intent = getIntent();
finish();
startActivity(intent);
}
Intent intent=new Intent(Current_Activity.this,Current_Activity.class);
startActivity(intent);
finish();
instantiate a new intent in your onBackPressed()
Since you are using two activities when you create intent from first activity to second activity the first activity onStop() is called and activity is put to back stack.When you press back button the first activity onCreate() is not called again but onResume() is called and activity is resumed.
So the logic that your are trying to should be done in onResume() such that it will be called every time when you press back button.For more reference check this.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
I've create an activity to change the locale of the application to load resources of the selected language and I restart the application,moreover I'm keeping an integer value as the app state using sharedpreferences,after setting the locale via the following code,the next time that I open the application the mentioned state does not have the correct value!!!!But,when I remove the language setting there isn't any problem with the state of the application!
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
/*
* Intent refresh = new Intent(this, AndroidLocalizeActivity.class);
* startActivity(refresh); finish();
*/
PrefManager _p = new PrefManager(getApplicationContext(), PrefConfigNames.LANGUAGE_APP_CONFIG);
_p.setStringValue(GeneralPrefKeyNames.LANGUAGE, lang);
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
setResult(RESULT_OK, null);
finish();
I cannot get what happens to sharedpreferences(I've used open source securepreferences (CodeProject article)in this app)
here!!!
Thanks in advance
Edit#1
PrefManager.java
public class PrefManager {
private SecurePreferences _securePreferences = null;
public PrefManager(Context context, String PrefName)
{
_securePreferences = new SecurePreferences(context, PrefName);
}
public void setStringValue(String key, String value)
{
_securePreferences.edit().putString(key, value).commit();
}
}
Edit#2
Something which is so weird is that the state of the application stored in the sharedprefs has the correct value when I debug or run the application from eclipse (debug or run as an android application)!!!but when I rerun it on the phone it has the default value!!!Please help me solve this issue!
Edit#3
I found out that there was a problem with relaunching the application using the following lines,is there another way to relaunch the app without any problem???Or even a better way (to update the language without relaunching the app)?
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
I've tried the following link to achieve the second mentioned approach
Changing locale: Force activity to reload resources?
,but it is not being raised after the following line
res.updateConfiguration(conf, dm);
Thanks in advance
I finally got the solution,in the onPause method I save the currently saved language in the sharedprefs and after changing the locale in the setting activity and returning to the previous activity in the onResume method I compare the newly saved lang with the value kept in the onPause,and if these two are not equal I call recreate method.
#Override
protected void onResume()
{
super.onResume();
SharedPreferences _sPreferences = getSharedPreferences(PrefConfigNames.LANGUAGE_APP_CONFIG,
Context.MODE_PRIVATE);
String resumeLang = _sPreferences.getString(GeneralPrefKeyNames.LANGUAGE, "En");
if (!currentLang.equals(resumeLang))
recreate();
};
#Override
protected void onPause()
{
SharedPreferences _sPreferences = getSharedPreferences(PrefConfigNames.LANGUAGE_APP_CONFIG,
Context.MODE_PRIVATE);
currentLang = _sPreferences.getString(GeneralPrefKeyNames.LANGUAGE, "En");
super.onPause();
};
You should commit() the values
I have implemented an option to select GUI language in my app, but I can't make it refresh the screen when a new language is selected.
The selection is made through a ListPreference so there are 2 problems :
1. Refresh the Preference page in which the language is selected.
2. When the app starts, I set the Locale on the onCreate() of the MainActivity but the MainActivity layout is never getting updated with the new selected Locale. (all other screens are updated so the set code is good).
Here is the code for setting the new Locale :
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
String langKey = ctx.getString(R.string.shared_options_select_language_key);
String langDefault = ctx.getString(R.string.shared_options_select_language_default_value);
String appLanguage = preferences.getString(langKey, langDefault);
Locale locale = null;
if (appLanguage.equals(langDefault)) {
locale = new Locale(Resources.getSystem().getConfiguration().locale.getLanguage());
} else {
String[] languageInfo = appLanguage.split("_");
if (languageInfo.length > 1) {
locale = new Locale(languageInfo[0], languageInfo[1]);
} else {
locale = new Locale(appLanguage);
}
}
if (appLanguage.contains(currentLang)) {
return false;
}
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
act.getBaseContext().getResources().updateConfiguration(config, act.getBaseContext().getResources().getDisplayMetrics());
Thank you
Try to refresh the MainActivity after selecting the new Locale
use this to reload the main activity or any activity
public void refrehs_me()
{
Intent intent = getIntent();
finish();
startActivity(intent);
}
Edit : As I can get from your explanation above you save the new locale selected in a shared preference.
Make a new boolean key in the shared preference called (locale_changed) - when a user select a new locale set this key to (TURE) and on the onCreate after setting the new locale check for this key if (TRUE) set it to (FALSE) and reload the activity.
on the second go it will not loop as the key remains (FALSE) until a user change the locale preference again.
The answer would be to position the call to setLocale right before setting the screen content :
setLocale();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
I already know how to change the language of my application (updating the configuration). My code also check if the configuration is changed by the system and "fix it" in the ´onCreate´ method. I even have created a ListPreference to let the user decide the language with one that my app supports (and saves the decision).
Let's say I have 3 activities (A, B and SettingsActivity). Activity A can start activities B and SettingsActivity. Activity B can start SettingsActivity. If the user changes the language inside SettingsActivity, I can update its resources (in this case Strings) without any problem using this code:
//if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
// Disabled because it blinks and looks bad
// recreate();
// } else {
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
// }
However, I'm unable to change the already open activities because I have no reference to them from SettingsActivity.
My question: is there any clean way to update the resources or recreate the already open activities? If I don't find a better solution, my approach will be one of the above:
Start activities using startActivityForResultand return a code to trigger the code I already use to recreate the activity.
Check inside the onResume method if the current language has changed and do the same thing.
At the end what I did was this:
#Override
protected void onStart() {
super.onStart();
if (!locale.equals(getResources().getConfiguration().locale)) {
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);
return;
}
}
Where locale is a variable assigned in my onCreate method:
private Locale locale;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((Application) getApplication()).refreshLanguage();
locale = getResources().getConfiguration().locale;
setContentView(R.layout.activity_main);
//moar code
}
Finally, for the sake of posting code, here is my refreshLanguage method(s):
boolean refreshLanguage() {
return refreshLanguage(PreferenceManager.getDefaultSharedPreferences(this));
}
boolean refreshLanguage(SharedPreferences sharedPreferences) {
if (sharedPreferences.contains("language")) {
int languageIndex = Integer.parseInt(sharedPreferences.getString("language", "0"));
if (!getResources().getConfiguration().locale.equals(languages[languageIndex])) {
Configuration config = new Configuration();
config.locale = languages[languageIndex];
getResources().updateConfiguration(config, null);
return true;
}
}
return false;
}
Notice that I use onStart rather than onResume because I'm not switching between transparent activities or using dialogs.
I have problem.
I have TabActivity with intent tabs.
In my application user can change language in preference settings.
When user change language and application go back to my TabActivity doing this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
finish();
startActivity(getIntent());
break;
default:
break;
}
}
This code run perfectly, because all text is in changed language.
Problem occur, when i restart application. Some texts are not in proper language (are in system default). When i open preference screen once again and back to my TabActivity, texts are all translated.
How can i translate all texts after restart application?
Why when i first run application not all texts are in proper language?
Im sorry for my English, i hope u understand what i mean and help me. Thank you.
This is code from preferenceActivity when saving:
String lang = preferences.getString("Language", "");
Configuration config = new Configuration();
if (!TextUtils.isEmpty(lang))
config.locale = new Locale(lang);
else
config.locale = Locale.getDefault();
Locale.setDefault(new Locale(lang));
getBaseContext().getResources().updateConfiguration(config, null);
tabActivity:
public class PlanActivity extends TabActivity {
SharedPreferences preferences;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.app_name);
preferences = getSharedPreferences(Constans.PREF, Activity.MODE_PRIVATE);
edytor = preferences.edit();
String lang = preferences.getString("Language", "en");
Configuration config = new Configuration();
if (!TextUtils.isEmpty(lang))
config.locale = new Locale(lang);
else
config.locale = Locale.getDefault();
Locale.setDefault(new Locale(lang));
getBaseContext().getResources().updateConfiguration(config, null);
setContentView(R.layout.main);
TabHost tabHost = getTabHost();
......... more
And this code is not working properly. I have to go to settings and go back to tabActivity for refresh texts
Are you correctly saving the changes to the SharedPreferences object? The code you provide does not show you using a SharedPreferences.Editor to save your changes.
EDIT: ensure that the preference file you're saving to in your preference Activity is the same one you're opening in your Tab activity (preferences = getSharedPreferences(Constans.PREF, Activity.MODE_PRIVATE);). If your tab activity does not find the preferences you're sure you saved in the preference activity then either your save code is not being called (either use a break point or a log statement to verify) or you are saving to the wrong file.