From 2e14002442e6b28e874011621747ca6a94ea05a8 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 18 Jun 2022 14:19:19 -0500 Subject: [PATCH] Switch to the new native per-app language preference APIs on Android 13 --- app/src/main/AndroidManifest.xml | 1 + .../preferences/LanguagePreference.java | 51 +++++++++++++++++++ .../preferences/PreferenceConfiguration.java | 6 +++ .../limelight/preferences/StreamSettings.java | 18 ++++--- .../java/com/limelight/utils/UiHelper.java | 36 ++++++++----- app/src/main/res/values/arrays.xml | 1 + app/src/main/res/xml/locales_config.xml | 21 ++++++++ app/src/main/res/xml/preferences.xml | 2 +- 8 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/limelight/preferences/LanguagePreference.java create mode 100644 app/src/main/res/xml/locales_config.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e4ccc15b..3886f9e2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -44,6 +44,7 @@ android:roundIcon="@mipmap/ic_launcher" android:installLocation="auto" android:gwpAsanMode="always" + android:localeConfig="@xml/locales_config" android:theme="@style/AppTheme"> = Build.VERSION_CODES.TIRAMISU) { + try { + // Launch the Android native app locale settings page + Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setData(Uri.parse("package:" + getContext().getPackageName())); + getContext().startActivity(intent, null); + return; + } catch (ActivityNotFoundException e) { + // App locale settings should be present on all Android 13 devices, + // but if not, we'll launch the old language chooser. + } + } + + // If we don't have native app locale settings, launch the normal dialog + super.onClick(); + } +} diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java index 83b483fa..8720ec00 100644 --- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java +++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java @@ -319,6 +319,12 @@ public class PreferenceConfiguration { .apply(); } + public static void completeLanguagePreferenceMigration(Context context) { + // Put our language option back to default which tells us that we've already migrated it + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putString(LANGUAGE_PREF_STRING, DEFAULT_LANGUAGE).apply(); + } + public static boolean isShieldAtvFirmwareWithBrokenHdr() { // This particular Shield TV firmware crashes when using HDR // https://www.nvidia.com/en-us/geforce/forums/notifications/comment/155192/ diff --git a/app/src/main/java/com/limelight/preferences/StreamSettings.java b/app/src/main/java/com/limelight/preferences/StreamSettings.java index ef3d4d3d..800aee33 100644 --- a/app/src/main/java/com/limelight/preferences/StreamSettings.java +++ b/app/src/main/java/com/limelight/preferences/StreamSettings.java @@ -80,16 +80,20 @@ public class StreamSettings extends Activity { } @Override + // NOTE: This will NOT be called on Android 13+ with android:enableOnBackInvokedCallback="true" public void onBackPressed() { finish(); - // Check for changes that require a UI reload to take effect - PreferenceConfiguration newPrefs = PreferenceConfiguration.readPreferences(this); - if (!newPrefs.language.equals(previousPrefs.language)) { - // Restart the PC view to apply UI changes - Intent intent = new Intent(this, PcView.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent, null); + // Language changes are handled via configuration changes in Android 13+, + // so manual activity relaunching is no longer required. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + PreferenceConfiguration newPrefs = PreferenceConfiguration.readPreferences(this); + if (!newPrefs.language.equals(previousPrefs.language)) { + // Restart the PC view to apply UI changes + Intent intent = new Intent(this, PcView.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent, null); + } } } diff --git a/app/src/main/java/com/limelight/utils/UiHelper.java b/app/src/main/java/com/limelight/utils/UiHelper.java index 7e54df94..4bbf4389 100644 --- a/app/src/main/java/com/limelight/utils/UiHelper.java +++ b/app/src/main/java/com/limelight/utils/UiHelper.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.GameManager; import android.app.GameState; +import android.app.LocaleManager; import android.app.UiModeManager; import android.content.Context; import android.content.DialogInterface; @@ -11,6 +12,7 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Insets; import android.os.Build; +import android.os.LocaleList; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; @@ -64,21 +66,29 @@ public class UiHelper { { String locale = PreferenceConfiguration.readPreferences(activity).language; if (!locale.equals(PreferenceConfiguration.DEFAULT_LANGUAGE)) { - Configuration config = new Configuration(activity.getResources().getConfiguration()); - - // Some locales include both language and country which must be separated - // before calling the Locale constructor. - if (locale.contains("-")) - { - config.locale = new Locale(locale.substring(0, locale.indexOf('-')), - locale.substring(locale.indexOf('-') + 1)); - } - else - { - config.locale = new Locale(locale); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + // On Android 13, migrate this non-default language setting into the OS native API + LocaleManager localeManager = activity.getSystemService(LocaleManager.class); + localeManager.setApplicationLocales(LocaleList.forLanguageTags(locale)); + PreferenceConfiguration.completeLanguagePreferenceMigration(activity); } + else { + Configuration config = new Configuration(activity.getResources().getConfiguration()); - activity.getResources().updateConfiguration(config, activity.getResources().getDisplayMetrics()); + // Some locales include both language and country which must be separated + // before calling the Locale constructor. + if (locale.contains("-")) + { + config.locale = new Locale(locale.substring(0, locale.indexOf('-')), + locale.substring(locale.indexOf('-') + 1)); + } + else + { + config.locale = new Locale(locale); + } + + activity.getResources().updateConfiguration(config, activity.getResources().getDisplayMetrics()); + } } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index cd334e44..d4bc7bb7 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -43,6 +43,7 @@ 71 + Default English diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml new file mode 100644 index 00000000..1f052e53 --- /dev/null +++ b/app/src/main/res/xml/locales_config.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 98ad679d..9a3627c2 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -165,7 +165,7 @@ android:title="@string/title_checkbox_enable_pip" android:summary="@string/summary_checkbox_enable_pip" android:defaultValue="false" /> -