androidkotlinandroid-jetpack-compose

How to restart Android Activities with new Locale?


I've created an Android Studio Application that aims to update language of several Jetpack Compose Activity classes. Part of the functions are moved to the helper class LanguageUtils.java:

class LanguageUtils {

    static String getCurrentLanguage(Context context) {
        SharedPreferences prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
        return prefs.getString("lang", "en");
    }

     static void saveLanguage(Context context, String language) {
        SharedPreferences prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
        prefs.edit().putString("lang", language).apply();
        Log.e("MyApplication", "getCurrentLanguage: " + getCurrentLanguage(context));
    }

    static Context setLocale(Context context, String lang) {

        Locale locale = new Locale(lang);
        Locale.setDefault(locale);

        Resources resources = context.getResources();
        Configuration resConfig = resources.getConfiguration();
        Configuration config = new Configuration(resConfig);

        config.setLocale(locale);

        return context.createConfigurationContext(config);

    }

}

The application itself has the following methods:

class MyApplication : Application() {

    override fun attachBaseContext(base: Context) {
        val currentLang = LanguageUtils.getCurrentLanguage(base)
        val newContext = LanguageUtils.setLocale(base, currentLang)
        super.attachBaseContext(newContext)
    }

    fun setAppLanguage(activity: Activity, language: String) {

        LanguageUtils.saveLanguage(activity, language)

        val intent = activity.intent
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
        activity.startActivity(intent)
        activity.finish()

    }

}

What I want to achieve is to trigger resource update in the activity by pressing a button (I use XML resources located in folders res/values for English and res/values-** for other languages and use them with stringResource(R.string.someString)). How to do this on Android?

I used a button inside my activity like this:

val context = LocalContext.current
Button(
  modifier = Modifier.padding(8.dp),
  onClick = {
     val app = context.applicationContext as MyApplication
        val activity = context as Activity
        app.setAppLanguage(activity, "pl")
  }
) { Text("Change to Polish") }

When I run this code, the activity is restarted (the visible swipe animation) but the texts remain in English. It's also worth noting that updateConfiguration() is marked as deprecated by Android Studio from API 25 (Android 7) and therefore I don't want to use it


Solution

  • What worked for me was to move MyApplication.attachBaseContext() to the activities and then use either recreate() or startActivity() + finish() to reload the activity.