Cambiar la configuración regional en tiempo de ejecución?

Tenemos una aplicación de Android que funciona como un cliente para un progtwig de PC remoto. Nos gustaría agregar una función para que la PC pueda indicarle a la aplicación de Android que cambie su configuración regional en tiempo de ejecución, es decir, inicie la aplicación; ponerlo en comunicación con la PC; algún tiempo después, la PC le dice a la aplicación que cambie a, por ejemplo, español o chino.

Ya tenemos todos los recursos de disposición y cadena configurados para sus respectivas configuraciones regionales. Nuestra aplicación es la única que el usuario ve, por lo que no importa si el rest del dispositivo se mantiene en inglés.

Hay otro hilo en Change language programmatically en Android pero no parece llegar a una conclusión.

Puedo poner . . .

Locale locale = new Locale(sTheNewLocale); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); 

. . . en onCreate () antes de setContentView () pero eso realmente no ayuda si quiero cambiar la configuración regional después de que mi pantalla esté funcionando. ¿Hay alguna forma de volver a cargar la vista de contenido una vez que la actividad ya se está ejecutando? Entonces, ¿ hay alguna manera práctica de cambiar las configuraciones regionales sobre la marcha de manera confiable o tengo que decirle a mi jefe que no se puede hacer, excepto para configurar todo el dispositivo en la nueva configuración regional antes de iniciar la aplicación?

Desde la API 11, puede utilizar la función recreate para que este método se pueda utilizar en su actividad:

 private void restartInLocale(Locale locale) { Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; Resources resources = getResources(); resources.updateConfiguration(config, resources.getDisplayMetrics()); recreate(); } 

Puede comenzar una nueva instancia de su actividad y salir de la anterior. Aquí hay un ejemplo completo (no probado) de cómo puede almacenar cualquier idioma deseado y reiniciar su aplicación. Solo necesita llamar a restartInLanguage con su idioma preferido.

 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); } // ... } 

He combinado @weston y @rekire (ambos +1) y lo he usado para manejar este caso de uso:

  • ActivityA => ActivityB => SettingsActivity-changeLocale

Después de changeLocale en SettingsActivity las actividades principales ActivityA y ActivityB también deben recrearse para reflejar la nueva configuración regional.

Mi solución: ActivityA y ActivityB heredan de LocalizedActivity que comprueba onResume si la configuración regional ha cambiado y desencadena una recreate() si es necesario

De modo que cada actividad que hereda de LocalizedActivity maneja automáticamente el cambio de configuración regional específica de la aplicación.

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

Aquí está la fuente de LocalizedActivity.java y SettingsActivity.java que se usan en mi proyecto A Photo Manager

La solución es usar los métodos setContentView y controlLanguage (también puede llamar a este método desde una clase Global) en CADA actividad en el método onResume después de configurar su configuración regional. Ejemplo:

 @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()); }