Removed locale manager loading languages in advance

Instead they are loaded on demand
This commit is contained in:
Viktor De Pasquale 2019-05-10 17:30:25 +02:00
parent 58a449d437
commit 9491ba77e0
8 changed files with 183 additions and 198 deletions

View File

@ -146,7 +146,7 @@ public class MagiskDB {
String dateString = null, newString;
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
Date date = new Date(values.getAsLong("time"));
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.getLocale()).format(date);
if (!TextUtils.equals(dateString, newString)) {
dateString = newString;
list = new ArrayList<>();

View File

@ -47,10 +47,10 @@ public class SuLogEntry {
}
public String getDateString() {
return DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
return DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.getLocale()).format(date);
}
public String getTimeString() {
return new SimpleDateFormat("h:mm a", LocaleManager.locale).format(date);
return new SimpleDateFormat("h:mm a", LocaleManager.getLocale()).format(date);
}
}

View File

@ -6,7 +6,6 @@ import android.text.TextUtils
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.topjohnwu.magisk.*
import com.topjohnwu.magisk.utils.LocaleManager
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.magisk.view.Shortcuts
@ -45,9 +44,6 @@ open class SplashActivity : AppCompatActivity() {
}
}
// Dynamic detect all locales
LocaleManager.loadAvailableLocales(R.string.app_changelog)
// Set default configs
Config.initialize()

View File

@ -10,7 +10,6 @@ import android.view.ViewGroup;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Event;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
@ -21,7 +20,7 @@ import androidx.preference.PreferenceViewHolder;
import androidx.recyclerview.widget.RecyclerView;
public abstract class BasePreferenceFragment extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener, Event.AutoListener {
implements SharedPreferences.OnSharedPreferenceChangeListener {
public App app = App.self;
@ -29,22 +28,15 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
app.getPrefs().registerOnSharedPreferenceChangeListener(this);
Event.register(this);
return v;
}
@Override
public void onDestroyView() {
app.getPrefs().unregisterOnSharedPreferenceChangeListener(this);
Event.unregister(this);
super.onDestroyView();
}
@Override
public int[] getListeningEvents() {
return new int[0];
}
@Override
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
return new PreferenceGroupAdapter(preferenceScreen) {

View File

@ -1,5 +1,6 @@
package com.topjohnwu.magisk.ui.settings;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
@ -14,7 +15,6 @@ import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.ui.base.BasePreferenceFragment;
import com.topjohnwu.magisk.utils.DownloadApp;
import com.topjohnwu.magisk.utils.Event;
import com.topjohnwu.magisk.utils.FingerprintHelper;
import com.topjohnwu.magisk.utils.LocaleManager;
import com.topjohnwu.magisk.utils.PatchAPK;
@ -25,7 +25,6 @@ import com.topjohnwu.superuser.Shell;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.ListPreference;
@ -33,6 +32,9 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreferenceCompat;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import kotlin.Pair;
public class SettingsFragment extends BasePreferenceFragment {
@ -115,6 +117,8 @@ public class SettingsFragment extends BasePreferenceFragment {
return true;
});
setLocalePreference((ListPreference) findPreference(Config.Key.LOCALE));
/* We only show canary channels if user is already on canary channel
* or the user have already chosen canary channel */
if (!Utils.isCanary() &&
@ -168,19 +172,36 @@ public class SettingsFragment extends BasePreferenceFragment {
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
@SuppressLint("CheckResult")
private void setLocalePreference(ListPreference lp) {
CharSequence[] entries = new CharSequence[LocaleManager.locales.size() + 1];
CharSequence[] entryValues = new CharSequence[LocaleManager.locales.size() + 1];
entries[0] = LocaleManager.getString(LocaleManager.defaultLocale, R.string.system_default);
entryValues[0] = "";
int i = 1;
for (Locale locale : LocaleManager.locales) {
entries[i] = locale.getDisplayName(locale);
entryValues[i++] = LocaleManager.toLanguageTag(locale);
}
lp.setEntries(entries);
lp.setEntryValues(entryValues);
lp.setSummary(LocaleManager.locale.getDisplayName(LocaleManager.locale));
lp.setSummary("Loading");
lp.setEnabled(false);
LocaleManager.getAvailableLocales()
.flattenAsFlowable(locales -> locales)
.map(locale -> new Pair<>(locale.getDisplayName(locale), LocaleManager.toLanguageTag(locale)))
.toList()
.map(list -> {
CharSequence[] names = new CharSequence[list.size() + 1];
CharSequence[] values = new CharSequence[list.size() + 1];
names[0] = LocaleManager.getString(LocaleManager.getDefaultLocale(), R.string.system_default);
values[0] = "";
int i = 1;
for (Pair<String, String> item : list) {
names[i] = item.getFirst();
values[i++] = item.getSecond();
}
return new Pair<>(names, values);
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(it -> {
lp.setEnabled(true);
lp.setEntries(it.getFirst());
lp.setEntryValues(it.getSecond());
lp.setSummary(LocaleManager.getLocale().getDisplayName(LocaleManager.getLocale()));
}, Throwable::printStackTrace);
}
@Override
@ -198,7 +219,8 @@ public class SettingsFragment extends BasePreferenceFragment {
if (prefs.getBoolean(key, false)) {
try {
Const.MAGISK_DISABLE_FILE.createNewFile();
} catch (IOException ignored) {}
} catch (IOException ignored) {
}
} else {
Const.MAGISK_DISABLE_FILE.delete();
}
@ -252,27 +274,27 @@ public class SettingsFragment extends BasePreferenceFragment {
break;
case Config.Key.ROOT_ACCESS:
rootConfig.setSummary(getResources()
.getStringArray(R.array.su_access)[(int)Config.get(key)]);
.getStringArray(R.array.su_access)[(int) Config.get(key)]);
break;
case Config.Key.SU_AUTO_RESPONSE:
autoRes.setSummary(getResources()
.getStringArray(R.array.auto_response)[(int)Config.get(key)]);
.getStringArray(R.array.auto_response)[(int) Config.get(key)]);
break;
case Config.Key.SU_NOTIFICATION:
suNotification.setSummary(getResources()
.getStringArray(R.array.su_notification)[(int)Config.get(key)]);
.getStringArray(R.array.su_notification)[(int) Config.get(key)]);
break;
case Config.Key.SU_REQUEST_TIMEOUT:
requestTimeout.setSummary(
getString(R.string.request_timeout_summary, (int)Config.get(key)));
getString(R.string.request_timeout_summary, (int) Config.get(key)));
break;
case Config.Key.SU_MULTIUSER_MODE:
multiuserConfig.setSummary(getResources()
.getStringArray(R.array.multiuser_summary)[(int)Config.get(key)]);
.getStringArray(R.array.multiuser_summary)[(int) Config.get(key)]);
break;
case Config.Key.SU_MNT_NS:
nsConfig.setSummary(getResources()
.getStringArray(R.array.namespace_summary)[(int)Config.get(key)]);
.getStringArray(R.array.namespace_summary)[(int) Config.get(key)]);
break;
}
}
@ -286,16 +308,4 @@ public class SettingsFragment extends BasePreferenceFragment {
setSummary(Config.Key.SU_MULTIUSER_MODE);
setSummary(Config.Key.SU_MNT_NS);
}
@Override
@Deprecated
public void onEvent(int event) {
setLocalePreference((ListPreference) findPreference(Config.Key.LOCALE));
}
@Override
@Deprecated
public int[] getListeningEvents() {
return new int[] {Event.LOCALE_FETCH_DONE};
}
}

View File

@ -1,148 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.Config;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.internal.InternalUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import androidx.annotation.StringRes;
public class LocaleManager {
public static Locale locale = Locale.getDefault();
public static final Locale defaultLocale = Locale.getDefault();
public static List<Locale> locales;
public static Locale forLanguageTag(String tag) {
if (Build.VERSION.SDK_INT >= 21) {
return Locale.forLanguageTag(tag);
} else {
String[] tok = tag.split("-");
if (tok.length == 0) {
return new Locale("");
}
String language;
switch (tok[0]) {
case "und":
language = ""; // Undefined
break;
case "fil":
language = "tl"; // Filipino
break;
default:
language = tok[0];
}
if (language.length() != 2 && language.length() != 3)
return new Locale("");
if (tok.length == 1)
return new Locale(language);
String country = tok[1];
if (country.length() != 2 && country.length() != 3)
return new Locale(language);
return new Locale(language, country);
}
}
public static String toLanguageTag(Locale loc) {
if (Build.VERSION.SDK_INT >= 21) {
return loc.toLanguageTag();
} else {
String language = loc.getLanguage();
String country = loc.getCountry();
String variant = loc.getVariant();
if (language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")) {
language = "und"; // Follow the Locale#toLanguageTag() implementation
} else if (language.equals("iw")) {
language = "he"; // correct deprecated "Hebrew"
} else if (language.equals("in")) {
language = "id"; // correct deprecated "Indonesian"
} else if (language.equals("ji")) {
language = "yi"; // correct deprecated "Yiddish"
}
// ensure valid country code, if not well formed, it's omitted
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) {
country = "";
}
// variant subtags that begin with a letter must be at least 5 characters long
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) {
variant = "";
}
StringBuilder tag = new StringBuilder(language);
if (!country.isEmpty())
tag.append('-').append(country);
if (!variant.isEmpty())
tag.append('-').append(variant);
return tag.toString();
}
}
public static void setLocale(ContextWrapper wrapper) {
String localeConfig = Config.get(Config.Key.LOCALE);
if (TextUtils.isEmpty(localeConfig)) {
locale = defaultLocale;
} else {
locale = forLanguageTag(localeConfig);
}
Locale.setDefault(locale);
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(locale));
}
public static Context getLocaleContext(Context context, Locale locale) {
Configuration config = new Configuration(context.getResources().getConfiguration());
config.setLocale(locale);
return context.createConfigurationContext(config);
}
public static Context getLocaleContext(Locale locale) {
return getLocaleContext(App.self.getBaseContext(), locale);
}
public static String getString(Locale locale, @StringRes int id) {
return getLocaleContext(locale).getString(id);
}
@Deprecated
public static void loadAvailableLocales(@StringRes int compareId) {
Shell.EXECUTOR.execute(() -> {
locales = new ArrayList<>();
HashSet<String> set = new HashSet<>();
Resources res = App.self.getResources();
Locale locale;
// Add default locale
locales.add(Locale.ENGLISH);
set.add(getString(Locale.ENGLISH, compareId));
// Add some special locales
locales.add(Locale.TAIWAN);
set.add(getString(Locale.TAIWAN, compareId));
locale = new Locale("pt", "BR");
locales.add(locale);
set.add(getString(locale, compareId));
// Other locales
for (String s : res.getAssets().getLocales()) {
locale = forLanguageTag(s);
if (set.add(getString(locale, compareId))) {
locales.add(locale);
}
}
Collections.sort(locales, (a, b) -> a.getDisplayName(a).compareTo(b.getDisplayName(b)));
Event.trigger(Event.LOCALE_FETCH_DONE);
});
}
}

View File

@ -0,0 +1,135 @@
package com.topjohnwu.magisk.utils
import android.content.Context
import android.content.ContextWrapper
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import androidx.annotation.StringRes
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.superuser.internal.InternalUtils
import io.reactivex.Single
import java.util.*
object LocaleManager {
@JvmStatic
var locale = Locale.getDefault()
@JvmStatic
val defaultLocale = Locale.getDefault()
@JvmStatic
val availableLocales = Single.fromCallable {
val compareId = R.string.app_changelog
val res: Resources by inject()
mutableListOf<Locale>().apply {
// Add default locale
add(Locale.ENGLISH)
// Add some special locales
add(Locale.TAIWAN)
add(Locale("pt", "BR"))
// Other locales
val otherLocales = res.assets.locales
.map { forLanguageTag(it) }
.distinctBy { getString(it, compareId) }
listOf("", "").toTypedArray()
addAll(otherLocales)
}.sortedWith(Comparator { a, b ->
a.getDisplayName(a).toLowerCase(a)
.compareTo(b.getDisplayName(b).toLowerCase(b))
})
}.cache()
private fun forLanguageTag(tag: String): Locale {
if (Build.VERSION.SDK_INT >= 21) {
return Locale.forLanguageTag(tag)
} else {
val tok = tag.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if (tok.isEmpty()) {
return Locale("")
}
val language = when (tok[0]) {
"und" -> "" // Undefined
"fil" -> "tl" // Filipino
else -> tok[0]
}
if (language.length != 2 && language.length != 3)
return Locale("")
if (tok.size == 1)
return Locale(language)
val country = tok[1]
return if (country.length != 2 && country.length != 3) Locale(language)
else Locale(language, country)
}
}
@JvmStatic
fun toLanguageTag(loc: Locale): String {
if (Build.VERSION.SDK_INT >= 21) {
return loc.toLanguageTag()
} else {
var language = loc.language
var country = loc.country
var variant = loc.variant
when {
language.isEmpty() || !language.matches("\\p{Alpha}{2,8}".toRegex()) ->
language = "und" // Follow the Locale#toLanguageTag() implementation
language == "iw" -> language = "he" // correct deprecated "Hebrew"
language == "in" -> language = "id" // correct deprecated "Indonesian"
language == "ji" -> language = "yi" // correct deprecated "Yiddish"
}
// ensure valid country code, if not well formed, it's omitted
// variant subtags that begin with a letter must be at least 5 characters long
// ensure valid country code, if not well formed, it's omitted
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}".toRegex())) {
country = ""
}
// variant subtags that begin with a letter must be at least 5 characters long
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}".toRegex())) {
variant = ""
}
val tag = StringBuilder(language)
if (country.isNotEmpty())
tag.append('-').append(country)
if (variant.isNotEmpty())
tag.append('-').append(variant)
return tag.toString()
}
}
@JvmStatic
fun setLocale(wrapper: ContextWrapper) {
val localeConfig = Config.get<String>(Config.Key.LOCALE)
locale = when {
localeConfig.isNullOrEmpty() -> defaultLocale
else -> forLanguageTag(localeConfig)
}
Locale.setDefault(locale)
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(locale))
}
@JvmStatic
fun getLocaleContext(context: Context, locale: Locale): Context {
val config = Configuration(context.resources.configuration)
config.setLocale(locale)
return context.createConfigurationContext(config)
}
@JvmStatic
fun getLocaleContext(locale: Locale): Context {
return getLocaleContext(App.self.baseContext, locale)
}
@JvmStatic
fun getString(locale: Locale, @StringRes id: Int): String {
return getLocaleContext(locale).getString(id)
}
}

View File

@ -71,7 +71,7 @@ public class Utils {
if (info.labelRes > 0) {
Resources res = pm.getResourcesForApplication(info);
Configuration config = new Configuration();
config.setLocale(LocaleManager.locale);
config.setLocale(LocaleManager.getLocale());
res.updateConfiguration(config, res.getDisplayMetrics());
return res.getString(info.labelRes);
}