Generate dictionary list from downloaded list
app/src/main/java/eu/lepiller/nani/DictionaryActivity.java
| 39 | 39 | setSupportActionBar(toolbar); | |
| 40 | 40 | ||
| 41 | 41 | final ListView list_view = findViewById(R.id.dictionary_view); | |
| 42 | + | final SwipeRefreshLayout refresher = findViewById(R.id.dictionary_refresh_layout); | |
| 43 | + | ||
| 42 | 44 | final ArrayList<Dictionary> dictionaries = DictionaryFactory.getDictionnaries(getApplicationContext()); | |
| 43 | 45 | adapter = new DictionariesAdapter(getApplicationContext(), dictionaries); | |
| 44 | 46 | list_view.setAdapter(adapter); | |
| 45 | 47 | ||
| 48 | + | if(dictionaries.size() == 0) { | |
| 49 | + | Snackbar.make(findViewById(R.id.dictionary_view), getString(R.string.no_dico_list), | |
| 50 | + | Snackbar.LENGTH_LONG).show(); | |
| 51 | + | new DownloadTask(refresher).execute(); | |
| 52 | + | } | |
| 53 | + | ||
| 46 | 54 | list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() { | |
| 47 | 55 | @Override | |
| 48 | 56 | public void onItemClick(AdapterView<?> parent, View view, int position, long id) { | |
… | |||
| 52 | 60 | } | |
| 53 | 61 | }); | |
| 54 | 62 | ||
| 55 | - | final SwipeRefreshLayout refresher = findViewById(R.id.dictionary_refresh_layout); | |
| 56 | 63 | refresher.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | |
| 57 | 64 | @Override | |
| 58 | 65 | public void onRefresh() { | |
… | |||
| 105 | 112 | protected void onPostExecute(Integer i) { | |
| 106 | 113 | super.onPostExecute(i); | |
| 107 | 114 | refresher.setRefreshing(false); | |
| 115 | + | DictionaryFactory.updatePackageList(); | |
| 108 | 116 | adapter.notifyDataSetChanged(); | |
| 109 | 117 | if(i == null) | |
| 110 | 118 | return; | |
app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java
| 1 | 1 | package eu.lepiller.nani.dictionary; | |
| 2 | 2 | ||
| 3 | 3 | import android.content.Context; | |
| 4 | + | import android.os.Build; | |
| 5 | + | import android.os.LocaleList; | |
| 6 | + | import android.util.ArrayMap; | |
| 7 | + | import android.util.Log; | |
| 4 | 8 | ||
| 9 | + | import java.io.BufferedReader; | |
| 5 | 10 | import java.io.File; | |
| 11 | + | import java.io.FileInputStream; | |
| 12 | + | import java.io.FileNotFoundException; | |
| 13 | + | import java.io.FileReader; | |
| 14 | + | import java.io.IOException; | |
| 6 | 15 | import java.net.MalformedURLException; | |
| 7 | 16 | import java.net.URL; | |
| 8 | 17 | import java.util.ArrayList; | |
| 18 | + | import java.util.HashMap; | |
| 19 | + | import java.util.List; | |
| 20 | + | import java.util.Locale; | |
| 21 | + | import java.util.Map; | |
| 9 | 22 | ||
| 10 | 23 | import eu.lepiller.nani.R; | |
| 11 | 24 | import eu.lepiller.nani.result.Result; | |
… | |||
| 14 | 27 | private static DictionaryFactory instance; | |
| 15 | 28 | private static ArrayList<Dictionary> dictionaries; | |
| 16 | 29 | private static File cacheDir; | |
| 30 | + | private static File listFile; | |
| 31 | + | private static List<String> languages; | |
| 32 | + | ||
| 33 | + | private static final int LIST_PARSER_NONE = 0; | |
| 34 | + | private static final int LIST_PARSER_SYNOPSIS = 1; | |
| 35 | + | private static final int LIST_PARSER_DESCRIPTION = 2; | |
| 36 | + | private static final String TAG = "FACTORY"; | |
| 17 | 37 | ||
| 18 | 38 | private DictionaryFactory(Context context) { | |
| 19 | 39 | cacheDir = context.getCacheDir(); | |
| 40 | + | listFile = new File(cacheDir + "/list"); | |
| 41 | + | languages = new ArrayList<>(); | |
| 42 | + | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
| 43 | + | LocaleList l = context.getResources().getConfiguration().getLocales(); | |
| 44 | + | for(int i=0;i<l.size();i++) { | |
| 45 | + | Locale locale = l.get(i); | |
| 46 | + | languages.add(locale.getISO3Language()); | |
| 47 | + | languages.add(locale.getLanguage()); | |
| 48 | + | languages.add(locale.getLanguage().split("[_-]+]")[0]); | |
| 49 | + | } | |
| 50 | + | } else { | |
| 51 | + | Locale locale = context.getResources().getConfiguration().locale; | |
| 52 | + | languages.add(locale.getISO3Language()); | |
| 53 | + | languages.add(locale.getLanguage()); | |
| 54 | + | languages.add(locale.getLanguage().split("[_-]+]")[0]); | |
| 55 | + | } | |
| 56 | + | languages.add("en"); | |
| 57 | + | Log.d(TAG, languages.toString()); | |
| 58 | + | updatePackageList(); | |
| 59 | + | } | |
| 60 | + | ||
| 61 | + | private static String chooseLanguage(Map<String, StringBuilder> data) { | |
| 62 | + | for(String l: languages) { | |
| 63 | + | if(data.containsKey(l)) | |
| 64 | + | return data.get(l).toString(); | |
| 65 | + | } | |
| 66 | + | return null; | |
| 67 | + | } | |
| 68 | + | ||
| 69 | + | public static void updatePackageList() { | |
| 20 | 70 | dictionaries = new ArrayList<>(); | |
| 21 | - | dictionaries.add(new RadicalDict("RadK", | |
| 22 | - | context.getString(R.string.dico_radk), | |
| 23 | - | context.getString(R.string.dico_radk_long), | |
| 24 | - | cacheDir, | |
| 25 | - | "https://nani.lepiller.eu/dicos/radicals.nani")); | |
| 26 | - | dictionaries.add(new JMDict("JMdict_e", | |
| 27 | - | context.getString(R.string.dico_jmdict_e), | |
| 28 | - | context.getString(R.string.dico_jmdict_long), | |
| 29 | - | cacheDir, | |
| 30 | - | "https://nani.lepiller.eu/dicos/JMdict_e.nani")); | |
| 31 | - | dictionaries.add(new JMDict("JMdict_dut", | |
| 32 | - | context.getString(R.string.dico_jmdict_dut), | |
| 33 | - | context.getString(R.string.dico_jmdict_long), | |
| 34 | - | cacheDir, | |
| 35 | - | "https://nani.lepiller.eu/dicos/JMdict_dut.nani")); | |
| 36 | - | dictionaries.add(new JMDict("JMdict_fre", | |
| 37 | - | context.getString(R.string.dico_jmdict_fre), | |
| 38 | - | context.getString(R.string.dico_jmdict_long), | |
| 39 | - | cacheDir, | |
| 40 | - | "https://nani.lepiller.eu/dicos/JMdict_fre.nani")); | |
| 41 | - | dictionaries.add(new JMDict("JMdict_ger", | |
| 42 | - | context.getString(R.string.dico_jmdict_ger), | |
| 43 | - | context.getString(R.string.dico_jmdict_long), | |
| 44 | - | cacheDir, | |
| 45 | - | "https://nani.lepiller.eu/dicos/JMdict_ger.nani")); | |
| 46 | - | dictionaries.add(new JMDict("JMdict_hun", | |
| 47 | - | context.getString(R.string.dico_jmdict_hun), | |
| 48 | - | context.getString(R.string.dico_jmdict_long), | |
| 49 | - | cacheDir, | |
| 50 | - | "https://nani.lepiller.eu/dicos/JMdict_hun.nani")); | |
| 51 | - | dictionaries.add(new JMDict("JMdict_rus", | |
| 52 | - | context.getString(R.string.dico_jmdict_rus), | |
| 53 | - | context.getString(R.string.dico_jmdict_long), | |
| 54 | - | cacheDir, | |
| 55 | - | "https://nani.lepiller.eu/dicos/JMdict_rus.nani")); | |
| 56 | - | dictionaries.add(new JMDict("JMdict_slv", | |
| 57 | - | context.getString(R.string.dico_jmdict_slv), | |
| 58 | - | context.getString(R.string.dico_jmdict_long), | |
| 59 | - | cacheDir, | |
| 60 | - | "https://nani.lepiller.eu/dicos/JMdict_slv.nani")); | |
| 61 | - | dictionaries.add(new JMDict("JMdict_spa", | |
| 62 | - | context.getString(R.string.dico_jmdict_spa), | |
| 63 | - | context.getString(R.string.dico_jmdict_long), | |
| 64 | - | cacheDir, | |
| 65 | - | "https://nani.lepiller.eu/dicos/JMdict_spa.nani")); | |
| 66 | - | dictionaries.add(new JMDict("JMdict_swe", | |
| 67 | - | context.getString(R.string.dico_jmdict_swe), | |
| 68 | - | context.getString(R.string.dico_jmdict_long), | |
| 69 | - | cacheDir, | |
| 70 | - | "https://nani.lepiller.eu/dicos/JMdict_swe.nani")); | |
| 71 | + | if(listFile.exists()) { | |
| 72 | + | try { | |
| 73 | + | BufferedReader br = new BufferedReader(new FileReader(listFile)); | |
| 74 | + | String line; | |
| 75 | + | ||
| 76 | + | Map<String, StringBuilder> synopsis = new HashMap<>(); | |
| 77 | + | Map<String, StringBuilder> description = new HashMap<>(); | |
| 78 | + | String sha256 = ""; | |
| 79 | + | int size = 0; | |
| 80 | + | String type = ""; | |
| 81 | + | int entries = 0; | |
| 82 | + | String url = ""; | |
| 83 | + | String name = ""; | |
| 84 | + | int current = LIST_PARSER_NONE; | |
| 85 | + | String currentLanguage = ""; | |
| 86 | + | ||
| 87 | + | while((line = br.readLine()) != null) { | |
| 88 | + | if(line.isEmpty()) { | |
| 89 | + | // create dictionary | |
| 90 | + | if(type.compareTo("radk") == 0) { | |
| 91 | + | dictionaries.add(new RadicalDict(name, | |
| 92 | + | chooseLanguage(synopsis), | |
| 93 | + | chooseLanguage(description), | |
| 94 | + | cacheDir, | |
| 95 | + | url)); | |
| 96 | + | } else if (type.compareTo("jmdict") == 0) { | |
| 97 | + | dictionaries.add(new JMDict(name, | |
| 98 | + | chooseLanguage(synopsis), | |
| 99 | + | chooseLanguage(description), | |
| 100 | + | cacheDir, | |
| 101 | + | url)); | |
| 102 | + | } | |
| 103 | + | } | |
| 104 | + | ||
| 105 | + | if(line.startsWith("[")) { | |
| 106 | + | name = line.substring(1, line.length() - 1); | |
| 107 | + | } else if(line.startsWith(" ")) { | |
| 108 | + | StringBuilder sb; | |
| 109 | + | switch (current) { | |
| 110 | + | case LIST_PARSER_DESCRIPTION: | |
| 111 | + | sb = description.get(currentLanguage); | |
| 112 | + | if(sb != null) { | |
| 113 | + | sb.append(" "); | |
| 114 | + | sb.append(line.trim()); | |
| 115 | + | } | |
| 116 | + | break; | |
| 117 | + | case LIST_PARSER_SYNOPSIS: | |
| 118 | + | sb = synopsis.get(currentLanguage); | |
| 119 | + | if(sb != null) { | |
| 120 | + | sb.append(" "); | |
| 121 | + | sb.append(line.trim()); | |
| 122 | + | } | |
| 123 | + | break; | |
| 124 | + | default: | |
| 125 | + | break; | |
| 126 | + | } | |
| 127 | + | } else if(line.startsWith("synopsis=")) { | |
| 128 | + | String[] content = line.split("="); | |
| 129 | + | currentLanguage = content[1]; | |
| 130 | + | current = LIST_PARSER_SYNOPSIS; | |
| 131 | + | StringBuilder sb = new StringBuilder(); | |
| 132 | + | sb.append(line.substring(10 + currentLanguage.length()).trim()); | |
| 133 | + | synopsis.put(currentLanguage, sb); | |
| 134 | + | } else if(line.startsWith("description=")) { | |
| 135 | + | String[] content = line.split("="); | |
| 136 | + | currentLanguage = content[1]; | |
| 137 | + | current = LIST_PARSER_DESCRIPTION; | |
| 138 | + | StringBuilder sb = new StringBuilder(); | |
| 139 | + | sb.append(line.substring(13 + currentLanguage.length()).trim()); | |
| 140 | + | description.put(currentLanguage, sb); | |
| 141 | + | } else if(line.startsWith("sha256=")) { | |
| 142 | + | sha256 = line.substring(7); | |
| 143 | + | } else if(line.startsWith("type=")) { | |
| 144 | + | type = line.substring(5); | |
| 145 | + | } else if(line.startsWith("url=")) { | |
| 146 | + | url = line.substring(4); | |
| 147 | + | } else if(line.startsWith("size=")) { | |
| 148 | + | size = Integer.parseInt(line.substring(5)); | |
| 149 | + | } else if(line.startsWith("entries=")) { | |
| 150 | + | entries = Integer.parseInt(line.substring(8)); | |
| 151 | + | } | |
| 152 | + | } | |
| 153 | + | } catch (FileNotFoundException e) { | |
| 154 | + | e.printStackTrace(); | |
| 155 | + | } catch (IOException e) { | |
| 156 | + | e.printStackTrace(); | |
| 157 | + | } | |
| 158 | + | } | |
| 71 | 159 | } | |
| 72 | 160 | ||
| 73 | 161 | public static void prepare(Context context) { | |
… | |||
| 125 | 213 | } | |
| 126 | 214 | ||
| 127 | 215 | public static File getListFile() { | |
| 128 | - | return new File(cacheDir + "/list"); | |
| 216 | + | return listFile; | |
| 129 | 217 | } | |
| 130 | 218 | } | |
app/src/main/res/values/strings.xml
| 60 | 60 | <string name="error_dico_url">Error fetching dictionary list: malformed URL.</string> | |
| 61 | 61 | <string name="error_dico_io">Error fetching dictionary list: cannot write to cache file.</string> | |
| 62 | 62 | <string name="error_dico_not_found">Error fetching dictionary list: cannot find it on server.</string> | |
| 63 | + | <string name="no_dico_list">Dictionary list not yet downloaded, updating???</string> | |
| 63 | 64 | ||
| 64 | 65 | <!-- Result view --> | |
| 65 | 66 | <string name="sense_number">%d.</string> |