]> gitweb.fperrin.net Git - Dictionary.git/blobdiff - src/com/hughes/android/dictionary/DictionaryApplication.java
Select app-specific storage by default.
[Dictionary.git] / src / com / hughes / android / dictionary / DictionaryApplication.java
index ae2a7c272db67ececee0a9e1e3c0c36170380fe6..3c351d9da35eb12fa31a999cca6d78aec931a6f8 100644 (file)
@@ -20,19 +20,22 @@ import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Environment;
 import android.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 android.support.v4.view.MenuItemCompat;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MenuItem.OnMenuItemClickListener;
 import com.hughes.android.dictionary.DictionaryInfo.IndexInfo;
 import com.hughes.android.dictionary.engine.Dictionary;
 import com.hughes.android.dictionary.engine.Language;
@@ -40,7 +43,7 @@ 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.text.Collator;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -59,10 +62,55 @@ public class DictionaryApplication extends Application {
 
     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)
+    // 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 = true;
+
     // Static, determined by resources (and locale).
     // Unordered.
     static Map<String, DictionaryInfo> DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = null;
 
+    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),
+
+        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);
+
+        Theme(final int themeId, final int tokenRowFg,
+              final int tokenRowFgColor,
+              final int tokenRowMainBg, final int tokenRowOtherBg,
+              final int normalRowBg) {
+            this.themeId = themeId;
+            this.tokenRowFg = tokenRowFg;
+            this.tokenRowFgColor = tokenRowFgColor;
+            this.tokenRowMainBg = tokenRowMainBg;
+            this.tokenRowOtherBg = tokenRowOtherBg;
+            this.normalRowBg = normalRowBg;
+        }
+
+        final int themeId;
+        final int tokenRowFg;
+        final int tokenRowFgColor;
+        final int tokenRowMainBg;
+        final int tokenRowOtherBg;
+        final int normalRowBg;
+    }
+
     // Useful:
     // http://www.loc.gov/standards/iso639-2/php/code_list.php
     public static final Map<String, LanguageResources> isoCodeToResources = new LinkedHashMap<String, LanguageResources>();
@@ -228,7 +276,7 @@ public class DictionaryApplication extends Application {
 
     }
 
-    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.
@@ -266,10 +314,10 @@ public class DictionaryApplication extends Application {
                 DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.put(
                         dictionaryInfo.uncompressedFilename, dictionaryInfo);
             }
-            reader.close();
         } catch (IOException e) {
             Log.e(LOG, "Failed to load downloadable dictionary lists.", e);
         }
+        try { reader.close(); } catch (IOException e) {}
     }
 
     private File dictDir;
@@ -315,8 +363,7 @@ public class DictionaryApplication extends Application {
         MenuItemCompat.setShowAsAction(about, MenuItem.SHOW_AS_ACTION_NEVER);
         about.setOnMenuItemClickListener(new OnMenuItemClickListener() {
             public boolean onMenuItemClick(final MenuItem menuItem) {
-                final Intent intent = new Intent().setClassName(AboutActivity.class
-                        .getPackage().getName(), AboutActivity.class.getCanonicalName());
+                final Intent intent = new Intent(getApplicationContext(), AboutActivity.class);
                 context.startActivity(intent);
                 return false;
             }
@@ -326,7 +373,7 @@ public class DictionaryApplication extends Application {
         MenuItemCompat.setShowAsAction(help, MenuItem.SHOW_AS_ACTION_NEVER);
         help.setOnMenuItemClickListener(new OnMenuItemClickListener() {
             public boolean onMenuItemClick(final MenuItem menuItem) {
-                context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent());
+                context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent(getApplicationContext()));
                 return false;
             }
         });
@@ -336,8 +383,7 @@ public class DictionaryApplication extends Application {
         preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() {
             public boolean onMenuItemClick(final MenuItem menuItem) {
                 PreferenceActivity.prefsMightHaveChanged = true;
-                final Intent intent = new Intent().setClassName(PreferenceActivity.class
-                        .getPackage().getName(), PreferenceActivity.class.getCanonicalName());
+                final Intent intent = new Intent(getApplicationContext(), PreferenceActivity.class);
                 context.startActivity(intent);
                 return false;
             }
@@ -349,27 +395,60 @@ public class DictionaryApplication extends Application {
             public boolean onMenuItemClick(final MenuItem menuItem) {
                 final Intent intent = new Intent(Intent.ACTION_VIEW);
                 intent.setData(Uri
-                        .parse("http://code.google.com/p/quickdic-dictionary/issues/entry"));
+                        .parse("http://github.com/rdoeffinger/Dictionary/issues"));
                 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);
+        if (dictDir.isDirectory() && dictDir.list().length > 0) {
+            return dir;
+        }
+        File efd = getApplicationContext().getExternalFilesDir(null);
+        if (efd != null) {
+            efd.mkdirs();
+            if (!dictDir.isDirectory() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                getApplicationContext().getExternalFilesDirs(null);
+            }
+            if (efd.isDirectory() && efd.canWrite() && checkFileCreate(efd)) {
+                return efd.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), "");
         if (dir.isEmpty()) {
-            final File defaultDictDir = new File(Environment.getExternalStorageDirectory(), "quickDic");
-            dir = defaultDictDir.getAbsolutePath();
+            dir = selectDefaultDir();
         }
         dictDir = new File(dir);
         dictDir.mkdirs();
+        if (!dictDir.isDirectory() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+             getApplicationContext().getExternalFilesDirs(null);
+        }
         return dictDir;
     }
 
+    static public 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) {
+        }
+        return res;
+    }
+
     public File getWordListFile() {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
         String file = prefs.getString(getString(R.string.wordListFileKey), "");
@@ -379,13 +458,13 @@ public class DictionaryApplication extends Application {
         return new File(file);
     }
 
-    public C.Theme getSelectedTheme() {
+    public Theme getSelectedTheme() {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
         final String theme = prefs.getString(getString(R.string.themeKey), "themeLight");
         if (theme.equals("themeLight")) {
-            return C.Theme.LIGHT;
+            return Theme.LIGHT;
         } else {
-            return C.Theme.DEFAULT;
+            return Theme.DEFAULT;
         }
     }
 
@@ -468,10 +547,7 @@ public class DictionaryApplication extends Application {
             button.setScaleType(ScaleType.FIT_CENTER);
             result = button;
         }
-        result.setMinimumWidth(languageButtonPixels);
-        result.setMinimumHeight(languageButtonPixels * 2 / 3);
-        // result.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
-        // LayoutParams.WRAP_CONTENT));
+        result.setLayoutParams(new LinearLayout.LayoutParams(languageButtonPixels, languageButtonPixels * 2 / 3));
         return result;
     }
 
@@ -484,14 +560,13 @@ public class DictionaryApplication extends Application {
     public synchronized void deleteDictionary(final DictionaryInfo dictionaryInfo) {
         while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename)) {
         }
-        ;
         dictionaryConfig.uncompressedFilenameToDictionaryInfo
                 .remove(dictionaryInfo.uncompressedFilename);
         getPath(dictionaryInfo.uncompressedFilename).delete();
         PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig);
     }
 
-    final Collator collator = Collator.getInstance();
+    final Comparator collator = USE_COLLATOR ? Collator.getInstance() : String.CASE_INSENSITIVE_ORDER;
     final Comparator<String> uncompressedFilenameComparator = new Comparator<String>() {
         @Override
         public int compare(String uncompressedFilename1, String uncompressedFilename2) {
@@ -526,7 +601,7 @@ public class DictionaryApplication extends Application {
             @Override
             public void run() {
                 final DictionaryConfig oldDictionaryConfig = new DictionaryConfig();
-                synchronized (this) {
+                synchronized (DictionaryApplication.this) {
                     oldDictionaryConfig.dictionaryFilesOrdered
                             .addAll(dictionaryConfig.dictionaryFilesOrdered);
                 }
@@ -534,7 +609,7 @@ public class DictionaryApplication extends Application {
                 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);
@@ -563,9 +638,8 @@ 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());
@@ -573,16 +647,21 @@ public class DictionaryApplication extends Application {
                                 file.getName(), dictionaryInfo);
                     }
                 } else {
-                    Log.w(LOG, "dictDir is not a diretory: " + getDictDir().getPath());
+                    Log.w(LOG, "dictDir is not a directory: " + getDictDir().getPath());
                 }
                 if (!toAddSorted.isEmpty()) {
                     Collections.sort(toAddSorted, uncompressedFilenameComparator);
                     newDictionaryConfig.dictionaryFilesOrdered.addAll(toAddSorted);
                 }
 
-                PersistentObjectCache.getInstance()
-                        .write(C.DICTIONARY_CONFIGS, newDictionaryConfig);
-                synchronized (this) {
+                try {
+                    PersistentObjectCache.getInstance()
+                                 .write(C.DICTIONARY_CONFIGS, newDictionaryConfig);
+                } catch (Exception e) {
+                    Log.e(LOG, "Failed persisting dictionary configs", e);
+                }
+
+                synchronized (DictionaryApplication.this) {
                     dictionaryConfig = newDictionaryConfig;
                 }