Apply locale updates correctly for appcompat-v1.2.0.

Fixes #9736

See https://developer.android.com/jetpack/androidx/releases/appcompat#1.2.0
for how the code is "correctly" applying a new configuration.

Co-authored-by: Cody Henthorne <cody@signal.org>
fork-5.53.8
Fumiaki Yoshimatsu 2020-09-26 10:35:18 -04:00 zatwierdzone przez Cody Henthorne
rodzic 7e347f5cce
commit a7d672f6b4
8 zmienionych plików z 70 dodań i 74 usunięć

Wyświetl plik

@ -408,7 +408,8 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
DynamicLanguageContextWrapper.updateContext(base);
super.attachBaseContext(base);
}
private static class ProviderInitializationException extends RuntimeException {

Wyświetl plik

@ -82,9 +82,13 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
private static final String PREFERENCE_CATEGORY_ADVANCED = "preference_category_advanced";
private static final String PREFERENCE_CATEGORY_DONATE = "preference_category_donate";
private static final String WAS_CONFIGURATION_UPDATED = "was_configuration_updated";
private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private boolean wasConfigurationUpdated = false;
@Override
protected void onPreCreate() {
dynamicTheme.onCreate(this);
@ -102,9 +106,17 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
initFragment(android.R.id.content, new BackupsPreferenceFragment());
} else if (icicle == null) {
initFragment(android.R.id.content, new ApplicationPreferenceFragment());
} else {
wasConfigurationUpdated = icicle.getBoolean(WAS_CONFIGURATION_UPDATED);
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(WAS_CONFIGURATION_UPDATED, wasConfigurationUpdated);
super.onSaveInstanceState(outState);
}
@Override
public void onResume() {
super.onResume();
@ -126,21 +138,28 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
} else {
// TODO [greyson] Navigation
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
if (wasConfigurationUpdated) {
setResult(MainActivity.RESULT_CONFIG_CHANGED);
} else {
setResult(RESULT_OK);
}
finish();
}
return true;
}
@Override
public void onBackPressed() {
onSupportNavigateUp();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(TextSecurePreferences.THEME_PREF)) {
DynamicTheme.setDefaultDayNightMode(this);
recreate();
} else if (key.equals(TextSecurePreferences.LANGUAGE_PREF)) {
wasConfigurationUpdated = true;
recreate();
Intent intent = new Intent(this, KeyCachingService.class);

Wyświetl plik

@ -3,21 +3,20 @@ package org.thoughtcrime.securesms;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageActivityHelper;
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
import java.util.Objects;
@ -40,7 +39,6 @@ public abstract class BaseActivity extends AppCompatActivity {
protected void onResume() {
super.onResume();
initializeScreenshotSecurity();
DynamicLanguageActivityHelper.recreateIfNotInCorrectLanguage(this, TextSecurePreferences.getLanguage(this));
}
@Override
@ -84,7 +82,18 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(newBase, TextSecurePreferences.getLanguage(newBase)));
super.attachBaseContext(newBase);
Configuration configuration = new Configuration();
configuration.uiMode = (configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | getDelegate().getLocalNightMode();
applyOverrideConfiguration(configuration);
}
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
DynamicLanguageContextWrapper.prepareOverrideConfiguration(this, overrideConfiguration);
super.applyOverrideConfiguration(overrideConfiguration);
}
private void logEvent(@NonNull String event) {

Wyświetl plik

@ -1,10 +1,12 @@
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.tracing.Trace;
import org.thoughtcrime.securesms.util.CommunicationActions;
@ -14,6 +16,8 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
@Trace
public class MainActivity extends PassphraseRequiredActivity {
public static final int RESULT_CONFIG_CHANGED = Activity.RESULT_FIRST_USER + 901;
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
private final MainNavigator navigator = new MainNavigator(this);
@ -52,6 +56,14 @@ public class MainActivity extends PassphraseRequiredActivity {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == MainNavigator.REQUEST_CONFIG_CHANGES && resultCode == RESULT_CONFIG_CHANGED) {
recreate();
}
}
public @NonNull MainNavigator getNavigator() {
return navigator;
}

Wyświetl plik

@ -18,6 +18,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
public class MainNavigator {
public static final int REQUEST_CONFIG_CHANGES = 901;
private final MainActivity activity;
public MainNavigator(@NonNull MainActivity activity) {
@ -65,10 +67,9 @@ public class MainNavigator {
public void goToAppSettings() {
Intent intent = new Intent(activity, ApplicationPreferencesActivity.class);
activity.startActivity(intent);
activity.startActivityForResult(intent, REQUEST_CONFIG_CHANGES);
}
public void goToArchiveList() {
getFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_from_end, R.anim.slide_to_start, R.anim.slide_from_start, R.anim.slide_to_end)

Wyświetl plik

@ -70,7 +70,6 @@ import org.thoughtcrime.securesms.util.IOFunction;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;

Wyświetl plik

@ -1,40 +0,0 @@
package org.thoughtcrime.securesms.util.dynamiclanguage;
import android.app.Activity;
import androidx.annotation.MainThread;
import androidx.core.os.ConfigurationCompat;
import org.thoughtcrime.securesms.logging.Log;
import java.util.Locale;
public final class DynamicLanguageActivityHelper {
private static final String TAG = Log.tag(DynamicLanguageActivityHelper.class);
private static String reentryProtection;
/**
* If the activity isn't in the specified language, it will restart the activity.
*/
@MainThread
public static void recreateIfNotInCorrectLanguage(Activity activity, String language) {
Locale currentActivityLocale = ConfigurationCompat.getLocales(activity.getResources().getConfiguration()).get(0);
Locale selectedLocale = LocaleParser.findBestMatchingLocaleForLanguage(language);
if (currentActivityLocale.equals(selectedLocale)) {
reentryProtection = "";
return;
}
String reentryKey = activity.getClass().getName() + ":" + selectedLocale;
if (!reentryKey.equals(reentryProtection)) {
reentryProtection = reentryKey;
Log.d(TAG, String.format("Activity Locale %s, Selected locale %s, restarting", currentActivityLocale, selectedLocale));
activity.recreate();
} else {
Log.d(TAG, String.format("Skipping recreate as looks like looping, Activity Locale %s, Selected locale %s", currentActivityLocale, selectedLocale));
}
}
}

Wyświetl plik

@ -2,7 +2,8 @@ package org.thoughtcrime.securesms.util.dynamiclanguage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.Locale;
@ -10,25 +11,19 @@ import java.util.Locale;
* Updates a context with an alternative language.
*/
public final class DynamicLanguageContextWrapper {
private DynamicLanguageContextWrapper() {}
public static Context updateContext(Context context, String language) {
final Locale newLocale = LocaleParser.findBestMatchingLocaleForLanguage(language);
public static void prepareOverrideConfiguration(Context context, Configuration base) {
String language = TextSecurePreferences.getLanguage(context);
Locale newLocale = LocaleParser.findBestMatchingLocaleForLanguage(language);
Locale.setDefault(newLocale);
final Resources resources = context.getResources();
final Configuration config = resources.getConfiguration();
final Configuration newConfig = copyWithNewLocale(config, newLocale);
resources.updateConfiguration(newConfig, resources.getDisplayMetrics());
return context;
base.setLocale(newLocale);
}
private static Configuration copyWithNewLocale(Configuration config, Locale locale) {
final Configuration copy = new Configuration(config);
copy.setLocale(locale);
return copy;
}
public static void updateContext(Context base) {
Configuration config = base.getResources().getConfiguration();
prepareOverrideConfiguration(base, config);
}
}