Change language without restarting activity - android

I have a method that translates my application from English to Swedish and back again if the user so wishes. However, I don't really like the fact that the activity restarts every time because it's giving me a hard time with the savedInstaceState and I've had several crashes because of this.
Here's how my method that changes language looks:
public void setApplicationLanguage(String language) {
myLocale = new Locale(language);
Resources res = activity.getResources();
DisplayMetrics display = res.getDisplayMetrics();
Configuration configuration = res.getConfiguration();
configuration.locale = myLocale;
res.updateConfiguration(configuration, display);
Intent refresh = new Intent(activity, StartupActivity.class);
activity.startActivity(refresh);
}
Is there any chance that the same function can be applied without the:
Intent refresh = new Intent(activity, StartupActivity.class);
activity.startActivity(refresh);
?

Try this
I also had this issue.I used the code below and then it changed the language without refreshing the activity
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
onConfigurationChanged(conf);
/*Intent refresh = new Intent(this, AndroidLocalize.class);
startActivity(refresh);*/
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
// refresh your views here
lblLang.setText(R.string.langselection);
super.onConfigurationChanged(newConfig);
// Checks the active language
if (newConfig.locale == Locale.ENGLISH) {
Toast.makeText(this, "English", Toast.LENGTH_SHORT).show();
} else if (newConfig.locale == Locale.FRENCH){
Toast.makeText(this, "French", Toast.LENGTH_SHORT).show();
}
}
declare in Manifest android:configChanges="locale"

You can replace the code:
Intent refresh = new Intent(activity, StartupActivity.class);
activity.startActivity(refresh);
With the method from Activity class:
recreate();
I hope your minimum SDK version will support because it was introduce in SDK 11. Your activity will be recreate as a new instance remember! Everything will be started afresh. From my experience it is fast compared to making a new Intent. But if you want to pass some data the method of using Intent is better than that! You can add extras to the Intent.

Create a singleton class:
public class Singleton {
private static Singleton mInstance = null;
private int repeat = 0;
public int getRepeat() {
return repeat;
}
public void setRepeat(int repeat) {
this.repeat = repeat;
}
}
Now you have a method that you can set and get the data, so make a method and put it under onResume() method, call your method and you can get and set the data like this:
Singleton.getInstance().setRepeat(1);
Singleton.getInstance().getRepeat();

Related

Change Language of the application programmatically without refreshing the whole app

I'm trying to change the language of the application according to the user's input. I tried using this code to change the language of the application and it's working pretty fine.
public void setLocale(String lang) {
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(MainActivity.this, MainActivity.class);
startActivity(refresh);
}
But the problem is that app has to restart/refresh in order to reload the resources.
Is this the correct approach to set the language of the app programmatically?
Is there any other way to change the language without refreshing the app?
Try with recreate() on your activity. This approach was successful in my case. If you are on Fragment, then use getActivity().recreate();
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Constants.APP_STATE.SAVED_LOCALE, localeString);
editor.apply();
getActivity().recreate();
Override following method of your activity:
#Override
protected void attachBaseContext(Context newBase) {
SharedPreferences prefs = newBase.getSharedPreferences(Constants.APP_STATE.STATE_SHARED_PREFERENCES, MODE_PRIVATE);
String localeString = prefs.getString(Constants.APP_STATE.SAVED_LOCALE, Constants.DEFAULTS.DEFAULT_LOCALE);
Locale myLocale = new Locale(localeString);
Locale.setDefault(myLocale);
Configuration config = newBase.getResources().getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
config.setLocale(myLocale);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
Context newContext = newBase.createConfigurationContext(config);
super.attachBaseContext(newContext);
return;
}
} else {
config.locale = myLocale;
}
super.attachBaseContext(newBase);
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
When user set wanted locale, what you want to do is to save it into some string in SharedPreferences and call recreate() of activity. This will then call attachBaseContext(Context context) and in this method proper locale will be set to configuration, then new context will be created with this configuration. After that, new context will be sent to super class which will update application context and proper locale will be shown.
It is also good because locale is automatically set when starting app next time.
Change locale is a Configuration which leads your acitivity restart. There are many other things have the same effect like orientation , keyboardHidden. Take care of your activity's states.
If restarting your activity requires that you recover large sets of
data, re-establish a network connection, or perform other intensive
operations, then a full restart due to a configuration change might be
a slow user experience. Also, it might not be possible for you to
completely restore your activity state with the Bundle that the system
saves for you with the onSaveInstanceState() callback—it is not
designed to carry large objects (such as bitmaps) and the data within
it must be serialized then deserialized, which can consume a lot of
memory and make the configuration change slow. In such a situation,
you can alleviate the burden of reinitializing part of your activity
by retaining a Fragment when your activity is restarted due to a
configuration change. This fragment can contain references to stateful
objects that you want to retain.
Not the best-practice, but you can handle it
<activity android:name=".MyActivity"
android:configChanges="locale"
android:label="#string/app_name">
Then in your Activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Do your stuff here
}
Remember to take care of your state. Using setRetainFragment(true) is a good approach. Read this
Yes your code is correct and if you want without refreshing the application
then In Your Application class you need to call this in onCreate() method
String languageSelected = "en";//selected language
Locale myLocale = new Locale(languageSelected);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
getActivity().onConfigurationChanged(conf);//Call this method
You need to perform this particular language to be selected on Application class.

Multi language android app during Runtime? [duplicate]

This question already has answers here:
Change app language programmatically in Android
(34 answers)
Closed 2 years ago.
My aim is to change an application language from English to Chinese during runtime, is there any suggestions?
language_spinner = (Spinner)findViewById(R.id.settings_language_spinner);
language_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (pos == 1){
Toast.makeText(parent.getContext(),"You have selected English",Toast.LENGTH_SHORT).show();
setLocale("en");
}else if (pos == 2){
Toast.makeText(parent.getContext(),"You have selected Chinese",Toast.LENGTH_SHORT).show();
setLocale("zh");
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
if (!conf.locale.getLanguage().equals(lang)) {
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(this, SettingsActivity.class);
startActivity(refresh);
finish();
}
}
This code is working properly with English but not working with Chinese
please help me in finding the solution ..
I can give you idea how you can implement this:
step 1: make string file for all texts in values directory as string-ch, ch is the code for Chinese language. and in code get every string with the getResources.getString(R.string.text_name); so that it can take string value at run time either English or Chinese.
step 2: now create method :
void changeLanguage(String language) {
Locale locale = new Locale(language);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
}
step 3: call this method where you want to change language suppose if you want to get changed language of you application according to device language then you can call as:
changeLanguage(Locale.getDefault().getLanguage());
Create below function in Util like class
public static void setLocale(Activity activity, String languageCode) {
Locale locale = new Locale(languageCode);
Locale.setDefault(locale);
Resources resources = activity.getResources();
Configuration config = resources.getConfiguration();
config.setLocale(locale);
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
Call this function from activity at the start. The original post with this code snippet can be found at Change app language programmatically in Android page.

should the app first start with the default language?

I have created 4 languages for the app. I can change the Lauaguage, ok, but if close the app and then start I it again, the app starts atfirst with the default string.xml.
How to let the app starts with the last selected Language ?
should I call the the methode by OnCreate in the mainActivity ?
#SuppressWarnings("deprecation")
public void setLocale(String lang) {
Locale myLocale = new Locale(lang);
DisplayMetrics dm = getResources().getDisplayMetrics();
Configuration conf = getResources().getConfiguration();
conf.locale = myLocale;
getResources().updateConfiguration(conf, dm);
Intent refresh = new Intent(this, Languages.class);
startActivity(refresh);
/* "en" = English
"hi" =Hindi
"fr" =French
"it" =Italian
"de" =German
"es" =Spanish
"ja" =Japanese
"ko" =Korean
"nl" =Dutch
"pt" =Portuguese
"ru" =Russian
"zh" =Chinese
"ar" = arabic
*/
}
How can the user change the default language ?
Why don't you store the selected language in shared preferences? That way you can always check for the selected language when your app starts, and then load the appropriate language file.
I have used a long Way like below but it works. Thanks :
OnResume :
selected_lang= myshared.getString("selected_lang","de");
lang_found= Integer.parseInt(myshared.getString("lang_found","0"));
setLocale(selected_lang);
#SuppressWarnings("deprecation")
public void setLocale(String lang) {
Locale myLocale = new Locale(lang);
DisplayMetrics dm = getResources().getDisplayMetrics();
Configuration conf = getResources().getConfiguration();
conf.locale = myLocale;
getResources().updateConfiguration(conf, dm);
if(lang_found==0) {
Intent refresh = new Intent(this, MainActivity.class);
startActivity(refresh);
lang_found=1;
}
#Override
protected void onDestroy() {
lang_found=0;
Save_setting();
super.onDestroy();
}

Restart a single task activity

I have a singleTask activity and my app supportsRtl, so when I try to change the language, this SingleTask activity is not affected so I need to restart it, Any help?
If you're using API 11 and above you can use the:
Activity.recreate()
If you need to support lower API use this to call your activity again:
Intent i = getIntent();
finish();
startActivity(i);
If we use this approach we don't need to restart the activity
change your app language with the following code:
public static void notifyForLanguageChange(Context context, String languageCode) {
Resources res = context.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(languageCode.toLowerCase());
res.updateConfiguration(conf, dm);
}
and after that change your screen labels with(i.e reload string resources)
public void setLabels() {
txtFirstView.setText(R.string.first);
txtSecondView.setText(R.string.second);
btnThirdView.setText(R.string.third);
}

SharedPrefs is resetting after Setting Locale of the Android Application

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

Categories

Resources