X-Git-Url: http://gitweb.fperrin.net/?p=Dictionary.git;a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Fdictionary%2FDictionaryApplication.java;h=1e3788be869e7d830511705e391282e1af33c0ca;hp=b8022cebe827e08c9fe5ed7edc68dffbbe0724a2;hb=c76660b2772122109529d3616289980a7084eeeb;hpb=62cf8d49e42297c05582c627d0c31d4b88d73c1d diff --git a/src/com/hughes/android/dictionary/DictionaryApplication.java b/src/com/hughes/android/dictionary/DictionaryApplication.java index b8022ce..1e3788b 100644 --- a/src/com/hughes/android/dictionary/DictionaryApplication.java +++ b/src/com/hughes/android/dictionary/DictionaryApplication.java @@ -14,7 +14,6 @@ package com.hughes.android.dictionary; -import android.app.Application; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -22,28 +21,19 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.net.Uri; import android.os.Build; import android.os.Environment; -import android.preference.PreferenceManager; +import android.support.v7.preference.PreferenceManager; import android.support.v4.view.MenuItemCompat; import android.util.Log; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; -import android.widget.Toast; import com.hughes.android.dictionary.DictionaryInfo.IndexInfo; import com.hughes.android.dictionary.engine.Dictionary; -import com.hughes.android.dictionary.engine.Language; -import com.hughes.android.dictionary.engine.Language.LanguageResources; import com.hughes.android.dictionary.engine.TransliteratorManager; import com.hughes.android.util.PersistentObjectCache; import com.hughes.util.ListUtil; -import com.ibm.icu.text.Collator; import java.io.BufferedReader; import java.io.File; @@ -53,22 +43,36 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -public class DictionaryApplication extends Application { +public enum DictionaryApplication { + INSTANCE; + + private Context appContext; static final String LOG = "QuickDicApp"; // If set to false, avoid use of ICU collator // Works well enough for most european languages, // gives faster startup and avoids crashes on some - // devices due to Dalvik bugs (e.g. ARMv6, S5570i, CM11). + // devices due to Dalvik bugs (e.g. ARMv6, S5570i, CM11) + // when using ICU4J. // Leave it enabled by default for correctness except // for my known broken development/performance test device config. - static public final boolean USE_COLLATOR = !android.os.Build.FINGERPRINT.equals("Samsung/cm_tassve/tassve:4.4.4/KTU84Q/20150211:userdebug/release-keys"); + //static public final boolean USE_COLLATOR = !android.os.Build.FINGERPRINT.equals("Samsung/cm_tassve/tassve:4.4.4/KTU84Q/20150211:userdebug/release-keys"); + public static final boolean USE_COLLATOR = true; + + public static final TransliteratorManager.ThreadSetup threadBackground = new TransliteratorManager.ThreadSetup() { + @Override + public void onThreadStart() { + // THREAD_PRIORITY_BACKGROUND seemed like a good idea, but it + // can make Transliterator go from 20 seconds to 3 minutes (!) + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE); + } + }; // Static, determined by resources (and locale). // Unordered. @@ -76,23 +80,23 @@ public class DictionaryApplication extends Application { enum Theme { DEFAULT(R.style.Theme_Default, - R.style.Theme_Default_TokenRow_Fg, - R.color.theme_default_token_row_fg, - R.drawable.theme_default_token_row_main_bg, - R.drawable.theme_default_token_row_other_bg, - R.drawable.theme_default_normal_row_bg), + R.style.Theme_Default_TokenRow_Fg, + R.color.theme_default_token_row_fg, + R.drawable.theme_default_token_row_main_bg, + R.drawable.theme_default_token_row_other_bg, + R.drawable.theme_default_normal_row_bg), LIGHT(R.style.Theme_Light, - R.style.Theme_Light_TokenRow_Fg, - R.color.theme_light_token_row_fg, - R.drawable.theme_light_token_row_main_bg, - R.drawable.theme_light_token_row_other_bg, - R.drawable.theme_light_normal_row_bg); + R.style.Theme_Light_TokenRow_Fg, + R.color.theme_light_token_row_fg, + R.drawable.theme_light_token_row_main_bg, + R.drawable.theme_light_token_row_other_bg, + R.drawable.theme_light_normal_row_bg); Theme(final int themeId, final int tokenRowFg, - final int tokenRowFgColor, - final int tokenRowMainBg, final int tokenRowOtherBg, - final int normalRowBg) { + final int tokenRowFgColor, + final int tokenRowMainBg, final int tokenRowOtherBg, + final int normalRowBg) { this.themeId = themeId; this.tokenRowFg = tokenRowFg; this.tokenRowFgColor = tokenRowFgColor; @@ -109,183 +113,18 @@ public class DictionaryApplication extends Application { final int normalRowBg; } - // Useful: - // http://www.loc.gov/standards/iso639-2/php/code_list.php - public static final Map isoCodeToResources = new LinkedHashMap(); - static { - isoCodeToResources.put("AF", new LanguageResources("Afrikaans", R.string.AF, - R.drawable.flag_of_south_africa)); - isoCodeToResources.put("SQ", new LanguageResources("Albanian", R.string.SQ, - R.drawable.flag_of_albania)); - isoCodeToResources.put("AR", - new LanguageResources("Arabic", R.string.AR, R.drawable.arabic)); - isoCodeToResources.put("HY", new LanguageResources("Armenian", R.string.HY, - R.drawable.flag_of_armenia)); - isoCodeToResources.put("BE", new LanguageResources("Belarusian", R.string.BE, - R.drawable.flag_of_belarus)); - isoCodeToResources.put("BN", new LanguageResources("Bengali", R.string.BN)); - isoCodeToResources.put("BS", new LanguageResources("Bosnian", R.string.BS, - R.drawable.flag_of_bosnia_and_herzegovina)); - isoCodeToResources.put("BG", new LanguageResources("Bulgarian", R.string.BG, - R.drawable.flag_of_bulgaria)); - isoCodeToResources.put("MY", new LanguageResources("Burmese", R.string.MY, - R.drawable.flag_of_myanmar)); - isoCodeToResources.put("ZH", new LanguageResources("Chinese", R.string.ZH, - R.drawable.flag_of_the_peoples_republic_of_china)); - isoCodeToResources.put("cmn", new LanguageResources("Mandarin", R.string.cmn, - R.drawable.flag_of_the_peoples_republic_of_china)); - isoCodeToResources.put("yue", new LanguageResources("Cantonese", R.string.yue, - R.drawable.flag_of_hong_kong)); - isoCodeToResources.put("CA", new LanguageResources("Catalan", R.string.CA)); - isoCodeToResources.put("HR", new LanguageResources("Croatian", R.string.HR, - R.drawable.flag_of_croatia)); - isoCodeToResources.put("CS", new LanguageResources("Czech", R.string.CS, - R.drawable.flag_of_the_czech_republic)); - isoCodeToResources.put("DA", new LanguageResources("Danish", R.string.DA, - R.drawable.flag_of_denmark)); - isoCodeToResources.put("NL", new LanguageResources("Dutch", R.string.NL, - R.drawable.flag_of_the_netherlands)); - isoCodeToResources.put("EN", new LanguageResources("English", R.string.EN, - R.drawable.flag_of_the_united_kingdom)); - isoCodeToResources.put("EO", new LanguageResources("Esperanto", R.string.EO, - R.drawable.flag_of_esperanto)); - isoCodeToResources.put("ET", new LanguageResources("Estonian", R.string.ET, - R.drawable.flag_of_estonia)); - isoCodeToResources.put("FI", new LanguageResources("Finnish", R.string.FI, - R.drawable.flag_of_finland)); - isoCodeToResources.put("FR", new LanguageResources("French", R.string.FR, - R.drawable.flag_of_france)); - isoCodeToResources.put("DE", new LanguageResources("German", R.string.DE, - R.drawable.flag_of_germany)); - isoCodeToResources.put("EL", new LanguageResources("Greek", R.string.EL, - R.drawable.flag_of_greece)); - isoCodeToResources.put("grc", new LanguageResources("Ancient Greek", R.string.grc)); - isoCodeToResources.put("haw", new LanguageResources("Hawaiian", R.string.haw, - R.drawable.flag_of_hawaii)); - isoCodeToResources.put("HE", new LanguageResources("Hebrew", R.string.HE, - R.drawable.flag_of_israel)); - isoCodeToResources.put("HI", new LanguageResources("Hindi", R.string.HI, R.drawable.hindi)); - isoCodeToResources.put("HU", new LanguageResources("Hungarian", R.string.HU, - R.drawable.flag_of_hungary)); - isoCodeToResources.put("IS", new LanguageResources("Icelandic", R.string.IS, - R.drawable.flag_of_iceland)); - isoCodeToResources.put("ID", new LanguageResources("Indonesian", R.string.ID, - R.drawable.flag_of_indonesia)); - isoCodeToResources.put("GA", new LanguageResources("Irish", R.string.GA, - R.drawable.flag_of_ireland)); - isoCodeToResources.put("GD", new LanguageResources("Scottish Gaelic", R.string.GD, - R.drawable.flag_of_scotland)); - isoCodeToResources.put("GV", new LanguageResources("Manx", R.string.GV, - R.drawable.flag_of_the_isle_of_man)); - isoCodeToResources.put("IT", new LanguageResources("Italian", R.string.IT, - R.drawable.flag_of_italy)); - isoCodeToResources.put("LA", new LanguageResources("Latin", R.string.LA)); - isoCodeToResources.put("LV", new LanguageResources("Latvian", R.string.LV, - R.drawable.flag_of_latvia)); - isoCodeToResources.put("LT", new LanguageResources("Lithuanian", R.string.LT, - R.drawable.flag_of_lithuania)); - isoCodeToResources.put("JA", new LanguageResources("Japanese", R.string.JA, - R.drawable.flag_of_japan)); - isoCodeToResources.put("KO", new LanguageResources("Korean", R.string.KO, - R.drawable.flag_of_south_korea)); - isoCodeToResources.put("KU", new LanguageResources("Kurdish", R.string.KU)); - isoCodeToResources.put("MS", new LanguageResources("Malay", R.string.MS, - R.drawable.flag_of_malaysia)); - isoCodeToResources.put("MI", new LanguageResources("Maori", R.string.MI, - R.drawable.flag_of_new_zealand)); - isoCodeToResources.put("MN", new LanguageResources("Mongolian", R.string.MN, - R.drawable.flag_of_mongolia)); - isoCodeToResources.put("NE", new LanguageResources("Nepali", R.string.NE, - R.drawable.flag_of_nepal)); - isoCodeToResources.put("NO", new LanguageResources("Norwegian", R.string.NO, - R.drawable.flag_of_norway)); - isoCodeToResources.put("FA", new LanguageResources("Persian", R.string.FA, - R.drawable.flag_of_iran)); - isoCodeToResources.put("PL", new LanguageResources("Polish", R.string.PL, - R.drawable.flag_of_poland)); - isoCodeToResources.put("PT", new LanguageResources("Portuguese", R.string.PT, - R.drawable.flag_of_portugal)); - isoCodeToResources.put("PA", new LanguageResources("Punjabi", R.string.PA)); - isoCodeToResources.put("RO", new LanguageResources("Romanian", R.string.RO, - R.drawable.flag_of_romania)); - isoCodeToResources.put("RU", new LanguageResources("Russian", R.string.RU, - R.drawable.flag_of_russia)); - isoCodeToResources.put("SA", new LanguageResources("Sanskrit", R.string.SA)); - isoCodeToResources.put("SR", new LanguageResources("Serbian", R.string.SR, - R.drawable.flag_of_serbia)); - isoCodeToResources.put("SK", new LanguageResources("Slovak", R.string.SK, - R.drawable.flag_of_slovakia)); - isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, - R.drawable.flag_of_slovenia)); - isoCodeToResources.put("SO", new LanguageResources("Somali", R.string.SO, - R.drawable.flag_of_somalia)); - isoCodeToResources.put("ES", new LanguageResources("Spanish", R.string.ES, - R.drawable.flag_of_spain)); - isoCodeToResources.put("SW", new LanguageResources("Swahili", R.string.SW)); - isoCodeToResources.put("SV", new LanguageResources("Swedish", R.string.SV, - R.drawable.flag_of_sweden)); - isoCodeToResources.put("TL", new LanguageResources("Tagalog", R.string.TL)); - isoCodeToResources.put("TG", new LanguageResources("Tajik", R.string.TG, - R.drawable.flag_of_tajikistan)); - isoCodeToResources.put("TH", new LanguageResources("Thai", R.string.TH, - R.drawable.flag_of_thailand)); - isoCodeToResources.put("BO", new LanguageResources("Tibetan", R.string.BO)); - isoCodeToResources.put("TR", new LanguageResources("Turkish", R.string.TR, - R.drawable.flag_of_turkey)); - isoCodeToResources.put("UK", new LanguageResources("Ukrainian", R.string.UK, - R.drawable.flag_of_ukraine)); - isoCodeToResources.put("UR", new LanguageResources("Urdu", R.string.UR)); - isoCodeToResources.put("VI", new LanguageResources("Vietnamese", R.string.VI, - R.drawable.flag_of_vietnam)); - isoCodeToResources.put("CI", new LanguageResources("Welsh", R.string.CI, - R.drawable.flag_of_wales_2)); - isoCodeToResources.put("YI", new LanguageResources("Yiddish", R.string.YI)); - isoCodeToResources.put("ZU", new LanguageResources("Zulu", R.string.ZU)); - isoCodeToResources.put("AZ", new LanguageResources("Azeri", R.string.AZ, - R.drawable.flag_of_azerbaijan)); - isoCodeToResources.put("EU", new LanguageResources("Basque", R.string.EU, - R.drawable.flag_of_the_basque_country)); - isoCodeToResources.put("BR", new LanguageResources("Breton", R.string.BR)); - isoCodeToResources.put("MR", new LanguageResources("Marathi", R.string.MR)); - isoCodeToResources.put("FO", new LanguageResources("Faroese", R.string.FO)); - isoCodeToResources.put("GL", new LanguageResources("Galician", R.string.GL, - R.drawable.flag_of_galicia)); - isoCodeToResources.put("KA", new LanguageResources("Georgian", R.string.KA, - R.drawable.flag_of_georgia)); - isoCodeToResources.put("HT", new LanguageResources("Haitian Creole", R.string.HT, - R.drawable.flag_of_haiti)); - isoCodeToResources.put("LB", new LanguageResources("Luxembourgish", R.string.LB, - R.drawable.flag_of_luxembourg)); - isoCodeToResources.put("MK", new LanguageResources("Macedonian", R.string.MK, - R.drawable.flag_of_macedonia)); - isoCodeToResources.put("LO", new LanguageResources("Lao", R.string.LO, - R.drawable.flag_of_laos)); - isoCodeToResources.put("ML", new LanguageResources("Malayalam", R.string.ML)); - isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, - R.drawable.flag_of_slovenia)); - isoCodeToResources.put("TA", new LanguageResources("Tamil", R.string.TA)); - isoCodeToResources.put("SH", new LanguageResources("Serbo-Croatian", R.string.SH)); - isoCodeToResources.put("SD", new LanguageResources("Sindhi", R.string.SD)); - - // Hack to allow lower-case ISO codes to work: - for (final String isoCode : new ArrayList(isoCodeToResources.keySet())) { - isoCodeToResources.put(isoCode.toLowerCase(), isoCodeToResources.get(isoCode)); - } - - } - - static final class DictionaryConfig implements Serializable { + public static final class DictionaryConfig implements Serializable { private static final long serialVersionUID = -1444177164708201263L; // User-ordered list, persisted, just the ones that are/have been // present. - final List dictionaryFilesOrdered = new ArrayList(); + final List dictionaryFilesOrdered = new ArrayList<>(); + + final Map uncompressedFilenameToDictionaryInfo = new HashMap<>(); - final Map uncompressedFilenameToDictionaryInfo = new LinkedHashMap(); - /** * Sometimes a deserialized version of this data structure isn't valid. - * @return */ + @SuppressWarnings("ConstantConditions") boolean isValid() { return uncompressedFilenameToDictionaryInfo != null && dictionaryFilesOrdered != null; } @@ -293,46 +132,49 @@ public class DictionaryApplication extends Application { DictionaryConfig dictionaryConfig = null; - int languageButtonPixels = -1; + public int languageButtonPixels = -1; static synchronized void staticInit(final Context context) { if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO != null) { return; } - DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = new LinkedHashMap(); + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = new HashMap<>(); final BufferedReader reader = new BufferedReader( - new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); + new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); try { String line; while ((line = reader.readLine()) != null) { - if (line.startsWith("#") || line.length() == 0) { + if (line.length() == 0 || line.charAt(0) == '#') { continue; } final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.put( - dictionaryInfo.uncompressedFilename, dictionaryInfo); + dictionaryInfo.uncompressedFilename, dictionaryInfo); } - reader.close(); } catch (IOException e) { Log.e(LOG, "Failed to load downloadable dictionary lists.", e); } + try { + reader.close(); + } catch (IOException ignored) {} } - private File dictDir; - - @Override - public void onCreate() { - super.onCreate(); + public synchronized void init(Context c) { + if (appContext != null) { + assert c == appContext; + return; + } + appContext = c; Log.d("QuickDic", "Application: onCreate"); - TransliteratorManager.init(null); - staticInit(getApplicationContext()); + TransliteratorManager.init(null, threadBackground); + staticInit(appContext); languageButtonPixels = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()); + TypedValue.COMPLEX_UNIT_DIP, 60, appContext.getResources().getDisplayMetrics()); // Load the dictionaries we know about. - dictionaryConfig = PersistentObjectCache.init(getApplicationContext()).read( - C.DICTIONARY_CONFIGS, DictionaryConfig.class); + dictionaryConfig = PersistentObjectCache.init(appContext).read( + C.DICTIONARY_CONFIGS, DictionaryConfig.class); if (dictionaryConfig == null) { dictionaryConfig = new DictionaryConfig(); } @@ -341,96 +183,125 @@ public class DictionaryApplication extends Application { } // Theme stuff. - setTheme(getSelectedTheme().themeId); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + appContext.setTheme(getSelectedTheme().themeId); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); prefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { + String key) { Log.d("QuickDic", "prefs changed: " + key); - if (key.equals(getString(R.string.themeKey))) { - setTheme(getSelectedTheme().themeId); + if (key.equals(appContext.getString(R.string.themeKey))) { + appContext.setTheme(getSelectedTheme().themeId); } } }); } - public void onCreateGlobalOptionsMenu( - final Context context, final Menu menu) { - final MenuItem about = menu.add(getString(R.string.about)); - MenuItemCompat.setShowAsAction(about, MenuItem.SHOW_AS_ACTION_NEVER); - about.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public static void onCreateGlobalOptionsMenu( + final Context context, final Menu menu) { + final Context c = context.getApplicationContext(); + + final MenuItem preferences = menu.add(c.getString(R.string.settings)); + MenuItemCompat.setShowAsAction(preferences, MenuItem.SHOW_AS_ACTION_NEVER); + preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = new Intent(getApplicationContext(), AboutActivity.class); + PreferenceActivity.prefsMightHaveChanged = true; + final Intent intent = new Intent(c, PreferenceActivity.class); context.startActivity(intent); return false; } }); - final MenuItem help = menu.add(getString(R.string.help)); + final MenuItem help = menu.add(c.getString(R.string.help)); MenuItemCompat.setShowAsAction(help, MenuItem.SHOW_AS_ACTION_NEVER); help.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { - context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent(getApplicationContext())); + context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent(c)); return false; } }); - final MenuItem preferences = menu.add(getString(R.string.settings)); - MenuItemCompat.setShowAsAction(preferences, MenuItem.SHOW_AS_ACTION_NEVER); - preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { + final MenuItem reportIssue = menu.add(c.getString(R.string.reportIssue)); + MenuItemCompat.setShowAsAction(reportIssue, MenuItem.SHOW_AS_ACTION_NEVER); + reportIssue.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { - PreferenceActivity.prefsMightHaveChanged = true; - final Intent intent = new Intent(getApplicationContext(), PreferenceActivity.class); + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri + .parse("https://github.com/rdoeffinger/Dictionary/issues")); context.startActivity(intent); return false; } }); - final MenuItem reportIssue = menu.add(getString(R.string.reportIssue)); - MenuItemCompat.setShowAsAction(reportIssue, MenuItem.SHOW_AS_ACTION_NEVER); - reportIssue.setOnMenuItemClickListener(new OnMenuItemClickListener() { + final MenuItem about = menu.add(c.getString(R.string.about)); + MenuItemCompat.setShowAsAction(about, MenuItem.SHOW_AS_ACTION_NEVER); + about.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri - .parse("http://github.com/rdoeffinger/Dictionary/issues")); + final Intent intent = new Intent(c, AboutActivity.class); context.startActivity(intent); return false; } }); } + private String selectDefaultDir() { + final File defaultDictDir = new File(Environment.getExternalStorageDirectory(), "quickDic"); + String dir = defaultDictDir.getAbsolutePath(); + File dictDir = new File(dir); + String[] fileList = dictDir.isDirectory() ? dictDir.list() : null; + if (fileList != null && fileList.length > 0) { + return dir; + } + File efd = null; + try { + efd = appContext.getExternalFilesDir(null); + } catch (Exception ignored) { + } + if (efd != null) { + efd.mkdirs(); + if (!dictDir.isDirectory() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + appContext.getExternalFilesDirs(null); + } + if (efd.isDirectory() && efd.canWrite() && checkFileCreate(efd)) { + return efd.getAbsolutePath(); + } + } + if (!dictDir.isDirectory() && !dictDir.mkdirs()) { + return appContext.getFilesDir().getAbsolutePath(); + } + return dir; + } + public synchronized File getDictDir() { // This metaphor doesn't work, because we've already reset // prefsMightHaveChanged. - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - String dir = prefs.getString(getString(R.string.quickdicDirectoryKey), ""); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + String dir = prefs.getString(appContext.getString(R.string.quickdicDirectoryKey), ""); if (dir.isEmpty()) { - final File defaultDictDir = new File(Environment.getExternalStorageDirectory(), "quickDic"); - dir = defaultDictDir.getAbsolutePath(); + dir = selectDefaultDir(); } - dictDir = new File(dir); + File dictDir = new File(dir); dictDir.mkdirs(); if (!dictDir.isDirectory() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - getApplicationContext().getExternalFilesDirs(null); + appContext.getExternalFilesDirs(null); } return dictDir; } - static public boolean checkFileCreate(File dir) { + public static boolean checkFileCreate(File dir) { boolean res = false; File testfile = new File(dir, "quickdic_writetest"); try { testfile.delete(); res = testfile.createNewFile() & testfile.delete(); - } catch (Exception e) { + } catch (Exception ignored) { } return res; } public File getWordListFile() { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - String file = prefs.getString(getString(R.string.wordListFileKey), ""); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + String file = prefs.getString(appContext.getString(R.string.wordListFileKey), ""); if (file.isEmpty()) { return new File(getDictDir(), "wordList.txt"); } @@ -438,8 +309,8 @@ public class DictionaryApplication extends Application { } public Theme getSelectedTheme() { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - final String theme = prefs.getString(getString(R.string.themeKey), "themeLight"); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + final String theme = prefs.getString(appContext.getString(R.string.themeKey), "themeLight"); if (theme.equals("themeLight")) { return Theme.LIGHT; } else { @@ -453,21 +324,13 @@ public class DictionaryApplication extends Application { String defaultLangISO2 = Locale.getDefault().getLanguage().toLowerCase(); String defaultLangName = null; - final Map fileToNameCache = new LinkedHashMap(); - - public String isoCodeToLocalizedLanguageName(final String isoCode) { - final Language.LanguageResources languageResources = isoCodeToResources - .get(isoCode); - final String lang = languageResources != null ? getApplicationContext().getString( - languageResources.nameId) : isoCode; - return lang; - } + final Map fileToNameCache = new HashMap<>(); public List sortedIndexInfos(List indexInfos) { // Hack to put the default locale first in the name. if (indexInfos.size() > 1 && indexInfos.get(1).shortName.toLowerCase().equals(defaultLangISO2)) { - List result = new ArrayList(indexInfos); + List result = new ArrayList<>(indexInfos); ListUtil.swap(result, 0, 1); return result; } @@ -482,7 +345,7 @@ public class DictionaryApplication extends Application { defaultLangName = null; } if (defaultLangName == null) { - defaultLangName = isoCodeToLocalizedLanguageName(defaultLangISO2); + defaultLangName = IsoUtils.INSTANCE.isoCodeToLocalizedLanguageName(appContext, defaultLangISO2); } String name = fileToNameCache.get(uncompressedFilename); @@ -491,7 +354,7 @@ public class DictionaryApplication extends Application { } final DictionaryInfo dictionaryInfo = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO - .get(uncompressedFilename); + .get(uncompressedFilename); if (dictionaryInfo != null) { final StringBuilder nameBuilder = new StringBuilder(); @@ -501,7 +364,7 @@ public class DictionaryApplication extends Application { nameBuilder.append("-"); } nameBuilder - .append(isoCodeToLocalizedLanguageName(sortedIndexInfos.get(i).shortName)); + .append(IsoUtils.INSTANCE.isoCodeToLocalizedLanguageName(appContext, sortedIndexInfos.get(i).shortName)); } name = nameBuilder.toString(); } else { @@ -511,41 +374,27 @@ public class DictionaryApplication extends Application { return name; } - public View createButton(final Context context, final DictionaryInfo dictionaryInfo, - final IndexInfo indexInfo) { - LanguageResources languageResources = isoCodeToResources.get(indexInfo.shortName); - View result; - - if (languageResources == null || languageResources.flagId <= 0) { - Button button = new Button(context); - button.setText(indexInfo.shortName); - result = button; - } else { - ImageButton button = new ImageButton(context); - button.setImageResource(languageResources.flagId); - button.setScaleType(ScaleType.FIT_CENTER); - result = button; - } - result.setLayoutParams(new LinearLayout.LayoutParams(languageButtonPixels, LinearLayout.LayoutParams.MATCH_PARENT)); - return result; - } - public synchronized void moveDictionaryToTop(final DictionaryInfo dictionaryInfo) { dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename); dictionaryConfig.dictionaryFilesOrdered.add(0, dictionaryInfo.uncompressedFilename); PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); } + public synchronized void sortDictionaries() { + Collections.sort(dictionaryConfig.dictionaryFilesOrdered, uncompressedFilenameComparator); + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + public synchronized void deleteDictionary(final DictionaryInfo dictionaryInfo) { while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename)) { } dictionaryConfig.uncompressedFilenameToDictionaryInfo - .remove(dictionaryInfo.uncompressedFilename); + .remove(dictionaryInfo.uncompressedFilename); getPath(dictionaryInfo.uncompressedFilename).delete(); PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); } - final Comparator collator = USE_COLLATOR ? Collator.getInstance() : String.CASE_INSENSITIVE_ORDER; + final Comparator collator = USE_COLLATOR ? CollatorWrapper.getInstance() : null; final Comparator uncompressedFilenameComparator = new Comparator() { @Override public int compare(String uncompressedFilename1, String uncompressedFilename2) { @@ -560,7 +409,7 @@ public class DictionaryApplication extends Application { return 1; } } - return collator.compare(name1, name2); + return collator != null ? collator.compare(name1, name2) : name1.compareToIgnoreCase(name2); } }; final Comparator dictionaryInfoComparator = new Comparator() { @@ -580,25 +429,25 @@ public class DictionaryApplication extends Application { @Override public void run() { final DictionaryConfig oldDictionaryConfig = new DictionaryConfig(); - synchronized (this) { + synchronized (DictionaryApplication.this) { oldDictionaryConfig.dictionaryFilesOrdered - .addAll(dictionaryConfig.dictionaryFilesOrdered); + .addAll(dictionaryConfig.dictionaryFilesOrdered); } final DictionaryConfig newDictionaryConfig = new DictionaryConfig(); for (final String uncompressedFilename : oldDictionaryConfig.dictionaryFilesOrdered) { final File dictFile = getPath(uncompressedFilename); final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(dictFile); - if (dictionaryInfo != null) { + if (dictionaryInfo.isValid() || dictFile.exists()) { newDictionaryConfig.dictionaryFilesOrdered.add(uncompressedFilename); newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put( - uncompressedFilename, dictionaryInfo); + uncompressedFilename, dictionaryInfo); } } // Are there dictionaries on the device that we didn't know // about already? // Pick them up and put them at the end of the list. - final List toAddSorted = new ArrayList(); + final List toAddSorted = new ArrayList<>(); final File[] dictDirFiles = getDictDir().listFiles(); if (dictDirFiles != null) { for (final File file : dictDirFiles) { @@ -617,14 +466,13 @@ public class DictionaryApplication extends Application { continue; } final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(file); - if (dictionaryInfo == null) { + if (!dictionaryInfo.isValid()) { Log.e(LOG, "Unable to parse dictionary: " + file.getPath()); - continue; } toAddSorted.add(file.getName()); newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put( - file.getName(), dictionaryInfo); + file.getName(), dictionaryInfo); } } else { Log.w(LOG, "dictDir is not a directory: " + getDictDir().getPath()); @@ -636,12 +484,12 @@ public class DictionaryApplication extends Application { try { PersistentObjectCache.getInstance() - .write(C.DICTIONARY_CONFIGS, newDictionaryConfig); + .write(C.DICTIONARY_CONFIGS, newDictionaryConfig); } catch (Exception e) { Log.e(LOG, "Failed persisting dictionary configs", e); } - synchronized (this) { + synchronized (DictionaryApplication.this) { dictionaryConfig = newDictionaryConfig; } @@ -654,13 +502,13 @@ public class DictionaryApplication extends Application { }).start(); } - public boolean matchesFilters(final DictionaryInfo dictionaryInfo, final String[] filters) { + private boolean matchesFilters(final DictionaryInfo dictionaryInfo, final String[] filters) { if (filters == null) { return true; } for (final String filter : filters) { if (!getDictionaryName(dictionaryInfo.uncompressedFilename).toLowerCase().contains( - filter)) { + filter)) { return false; } } @@ -668,11 +516,11 @@ public class DictionaryApplication extends Application { } public synchronized List getDictionariesOnDevice(String[] filters) { - final List result = new ArrayList( + final List result = new ArrayList<>( dictionaryConfig.dictionaryFilesOrdered.size()); for (final String uncompressedFilename : dictionaryConfig.dictionaryFilesOrdered) { final DictionaryInfo dictionaryInfo = dictionaryConfig.uncompressedFilenameToDictionaryInfo - .get(uncompressedFilename); + .get(uncompressedFilename); if (dictionaryInfo != null && matchesFilters(dictionaryInfo, filters)) { result.add(dictionaryInfo); } @@ -681,10 +529,10 @@ public class DictionaryApplication extends Application { } public List getDownloadableDictionaries(String[] filters) { - final List result = new ArrayList( + final List result = new ArrayList<>( dictionaryConfig.dictionaryFilesOrdered.size()); - final Map remaining = new LinkedHashMap( + final Map remaining = new HashMap<>( DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO); remaining.keySet().removeAll(dictionaryConfig.dictionaryFilesOrdered); for (final DictionaryInfo dictionaryInfo : remaining.values()) { @@ -696,22 +544,16 @@ public class DictionaryApplication extends Application { return result; } - public synchronized boolean isDictionaryOnDevice(String uncompressedFilename) { - return dictionaryConfig.uncompressedFilenameToDictionaryInfo.get(uncompressedFilename) != null; - } - public boolean updateAvailable(final DictionaryInfo dictionaryInfo) { final DictionaryInfo downloadable = - DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get( - dictionaryInfo.uncompressedFilename); + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get( + dictionaryInfo.uncompressedFilename); return downloadable != null && - downloadable.creationMillis > dictionaryInfo.creationMillis; + downloadable.creationMillis > dictionaryInfo.creationMillis; } public DictionaryInfo getDownloadable(final String uncompressedFilename) { - final DictionaryInfo downloadable = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO - .get(uncompressedFilename); - return downloadable; + return DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get(uncompressedFilename); } }