From fbf9932be3f44f7e43f2672217a6ce05f23668f8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 5 Jun 2015 17:09:10 -0400 Subject: [PATCH] rework setting locale from pref to have a lighter touch and be dynamic This leaves the default Locale unchanged, i.e. Locale.setDefault(). This also will immediately change the language after the user selects it in the pref. --- src/org/torproject/android/OrbotApp.java | 119 ++++++++++-------- .../torproject/android/OrbotMainActivity.java | 46 ++----- .../android/settings/SettingsPreferences.java | 45 ++++--- 3 files changed, 97 insertions(+), 113 deletions(-) diff --git a/src/org/torproject/android/OrbotApp.java b/src/org/torproject/android/OrbotApp.java index 744d5383..070d7d73 100644 --- a/src/org/torproject/android/OrbotApp.java +++ b/src/org/torproject/android/OrbotApp.java @@ -1,72 +1,87 @@ + package org.torproject.android; -import java.util.Locale; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.Application; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import info.guardianproject.util.Languages; import org.torproject.android.service.TorServiceUtils; -import android.app.Activity; -import android.app.Application; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.preference.PreferenceManager; - -import info.guardianproject.util.Languages; +import java.util.Locale; public class OrbotApp extends Application implements OrbotConstants { - private Locale locale; - private final static String DEFAULT_LOCALE = "en"; - private SharedPreferences settings; - - @Override + private Locale locale; + private SharedPreferences prefs; + + @Override public void onCreate() { super.onCreate(); - - settings = TorServiceUtils.getSharedPrefs(getApplicationContext()); - Configuration config = getResources().getConfiguration(); - - String lang = settings.getString(PREF_DEFAULT_LOCALE, DEFAULT_LOCALE); - - if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) - { - if (lang.equals("xx")) - { - locale = Locale.getDefault(); - - } - else - locale = new Locale(lang); - - Locale.setDefault(locale); - - Configuration myConfig = new Configuration(config); - myConfig.locale = locale; - - getResources().updateConfiguration(myConfig, getResources().getDisplayMetrics()); - } - - + prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + setNewLocale(prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage())); } - + @Override - public void onConfigurationChanged(Configuration newConfig) - { + public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + Log.i(TAG, "onConfigurationChanged " + newConfig.locale.getLanguage()); + setNewLocale(prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage())); + } - String lang = settings.getString(PREF_DEFAULT_LOCALE, DEFAULT_LOCALE); + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + public void setNewLocale(String language) { + if (TextUtils.isEmpty(language)) + return; - if (! "".equals(lang) && ! newConfig.locale.getLanguage().equals(lang)) - { - locale = new Locale(lang); - Locale.setDefault(locale); - - Configuration myConfig = new Configuration(newConfig); - myConfig.locale = locale; - - getResources().updateConfiguration(myConfig, getResources().getDisplayMetrics()); - } + if (locale != null && TextUtils.equals(locale.getLanguage(), language)) + return; // already configured + + /* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */ + String localeSplit[] = language.split("_"); + if (localeSplit.length > 1) + locale = new Locale(localeSplit[0], localeSplit[1]); + else + locale = new Locale(language); + Configuration config = getResources().getConfiguration(); + if (Build.VERSION.SDK_INT >= 17) + config.setLocale(locale); + else + config.locale = locale; + getResources().updateConfiguration(config, getResources().getDisplayMetrics()); + + /* + * Set the preference after setting the locale in case something goes + * wrong. If setting the locale causes an Exception, it should be set in + * the preferences, otherwise ChatSecure will be stuck in a crash loop. + */ + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(this); + Editor prefEdit = prefs.edit(); + prefEdit.putString(PREF_DEFAULT_LOCALE, language); + prefEdit.apply(); + Log.i(TAG, "setNewLocale complete: locale: " + locale.getLanguage() + + " Locale.getDefault: " + Locale.getDefault().getLanguage()); + } + + public static void forceChangeLanguage(Activity activity) { + Intent intent = activity.getIntent(); + if (intent == null) // when launched as LAUNCHER + intent = new Intent(activity, OrbotMainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + activity.finish(); + activity.overridePendingTransition(0, 0); + activity.startActivity(intent); + activity.overridePendingTransition(0, 0); } public static Languages getLanguages(Activity activity) { diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 3e577ad5..a721a456 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -95,6 +95,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private final static long INIT_DELAY = 100; private final static int REQUEST_VPN = 8888; + private final static int REQUEST_SETTINGS = 0x9874; /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { @@ -102,8 +103,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); mPrefs.registerOnSharedPreferenceChangeListener(this); - - setLocale(); doLayout(); @@ -390,7 +389,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon if (item.getItemId() == R.id.menu_settings) { - showSettings(); + Intent intent = new Intent(OrbotMainActivity.this, SettingsPreferences.class); + startActivityForResult(intent, REQUEST_SETTINGS); } else if (item.getItemId() == R.id.menu_wizard) { @@ -804,25 +804,15 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon { return false; } - } - - /* - * Load the basic settings application to display torrc - */ - private void showSettings () - { - - startActivityForResult(new Intent(this, SettingsPreferences.class), 1); - } - + } @Override protected void onActivityResult(int request, int response, Intent data) { super.onActivityResult(request, response, data); - - - if (request == 1 && response == RESULT_OK) + + if (request == REQUEST_SETTINGS && response == RESULT_OK) { + OrbotApp.forceChangeLanguage(this); if (data != null && data.getBooleanExtra("transproxywipe", false)) { @@ -1160,13 +1150,11 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon boolean useBridges = mPrefs.getBoolean("pref_bridges_enabled", false); mBtnBridges.setChecked(useBridges); } - + mHandler.postDelayed(new Runnable () { public void run () { - - setLocale(); handleIntents(); @@ -1427,24 +1415,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon }; - - // this is the connection that gets called back when a successfull bind occurs - // we should use this to activity monitor unbind so that we don't have to call - // bindService() a million times - - private void setLocale () - { - Configuration config = getResources().getConfiguration(); - String lang = mPrefs.getString(PREF_DEFAULT_LOCALE, ""); - - if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) - { - Locale locale = new Locale(lang); - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); - } - } @Override protected void onDestroy() { diff --git a/src/org/torproject/android/settings/SettingsPreferences.java b/src/org/torproject/android/settings/SettingsPreferences.java index f20898be..5c02d2be 100644 --- a/src/org/torproject/android/settings/SettingsPreferences.java +++ b/src/org/torproject/android/settings/SettingsPreferences.java @@ -6,12 +6,12 @@ package org.torproject.android.settings; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; import android.widget.Toast; @@ -20,6 +20,7 @@ import info.guardianproject.util.Languages; import org.sufficientlysecure.rootcommands.RootCommands; import org.sufficientlysecure.rootcommands.Shell; +import org.torproject.android.OrbotApp; import org.torproject.android.R; import org.torproject.android.service.TorServiceUtils; @@ -56,6 +57,26 @@ public class SettingsPreferences Languages languages = Languages.get(this, R.string.menu_settings, "Settings"); prefLocale.setEntries(languages.getAllNames()); prefLocale.setEntryValues(languages.getSupportedLocales()); + prefLocale.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String language = (String) newValue; + if (preference == prefLocale) { + SharedPreferences settings = TorServiceUtils + .getSharedPrefs(getApplicationContext()); + + String lang = settings.getString("pref_default_locale", + Locale.getDefault().getLanguage()); + OrbotApp app = (OrbotApp) getApplication(); + app.setNewLocale(language); + lang = settings.getString("pref_default_locale", + Locale.getDefault().getLanguage()); + OrbotApp.forceChangeLanguage(SettingsPreferences.this); + } + return false; + } + }); prefCBTransProxy = (CheckBoxPreference) findPreference("pref_transparent"); prefcBTransProxyAll = (CheckBoxPreference) findPreference("pref_transparent_all"); @@ -131,28 +152,6 @@ public class SettingsPreferences { prefHiddenServicesPorts.setEnabled(prefHiddenServices.isChecked()); prefHiddenServicesHostname.setEnabled(prefHiddenServices.isChecked()); - } - else if (preference == prefLocale) - { - SharedPreferences settings = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - Configuration config = getResources().getConfiguration(); - - String lang = settings.getString("pref_default_locale", "en"); - - Locale locale; - - if (lang.equals("xx")) - { - locale = Locale.getDefault(); - } - else - locale = new Locale(lang); - - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); - } else {