From 9c9dd489fc07121b6953d43bebb769c383e18ab0 Mon Sep 17 00:00:00 2001 From: sspanak Date: Wed, 13 Nov 2024 10:51:46 +0200 Subject: [PATCH] added an AssetFile class for easier asset management --- .../sspanak/tt9/db/entities/WordFile.java | 20 ++----- .../tt9/languages/LanguageDefinition.java | 58 ++++++++++--------- .../sspanak/tt9/preferences/HelpActivity.java | 20 ++----- .../sspanak/tt9/preferences/HelpFile.java | 17 ++++++ .../screens/main/MainSettingsScreen.java | 4 +- .../io/github/sspanak/tt9/util/AssetFile.java | 38 ++++++++++++ 6 files changed, 96 insertions(+), 61 deletions(-) create mode 100644 app/src/main/java/io/github/sspanak/tt9/preferences/HelpFile.java create mode 100644 app/src/main/java/io/github/sspanak/tt9/util/AssetFile.java diff --git a/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java b/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java index 945ff1f4..00dc59a0 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/entities/WordFile.java @@ -18,14 +18,13 @@ import java.util.zip.ZipInputStream; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.preferences.settings.SettingsStore; +import io.github.sspanak.tt9.util.AssetFile; import io.github.sspanak.tt9.util.Logger; -public class WordFile { +public class WordFile extends AssetFile { private static final String LOG_TAG = WordFile.class.getSimpleName(); - private final AssetManager assets; private final Context context; - private final String path; private int lastCharCode; private BufferedReader reader; @@ -38,9 +37,8 @@ public class WordFile { public WordFile(Context context, String path, AssetManager assets) { - this.assets = assets; + super(assets, path); this.context = context; - this.path = path; lastCharCode = 0; reader = null; @@ -64,16 +62,6 @@ public class WordFile { } - public boolean exists() { - try { - assets.open(path).close(); - return true; - } catch (IOException e) { - return false; - } - } - - public InputStream getRemoteStream() throws IOException { URLConnection connection = new URL(getDownloadUrl()).openConnection(); connection.setConnectTimeout(SettingsStore.DICTIONARY_DOWNLOAD_CONNECTION_TIMEOUT); @@ -87,7 +75,7 @@ public class WordFile { return reader; } - InputStream stream = exists() ? assets.open(path) : getRemoteStream(); + InputStream stream = exists() ? getStream() : getRemoteStream(); ZipInputStream zipStream = new ZipInputStream(stream); ZipEntry entry = zipStream.getNextEntry(); if (entry == null) { diff --git a/app/src/main/java/io/github/sspanak/tt9/languages/LanguageDefinition.java b/app/src/main/java/io/github/sspanak/tt9/languages/LanguageDefinition.java index c3bc3deb..d6228d41 100644 --- a/app/src/main/java/io/github/sspanak/tt9/languages/LanguageDefinition.java +++ b/app/src/main/java/io/github/sspanak/tt9/languages/LanguageDefinition.java @@ -7,15 +7,14 @@ import androidx.annotation.Nullable; import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import io.github.sspanak.tt9.BuildConfig; +import io.github.sspanak.tt9.util.AssetFile; import io.github.sspanak.tt9.util.Logger; -public class LanguageDefinition { +public class LanguageDefinition extends AssetFile { private static final String languagesDir = "languages"; private static final String definitionsDir = languagesDir + "/definitions"; @@ -28,6 +27,11 @@ public class LanguageDefinition { public String name = ""; + public LanguageDefinition(AssetManager assets, String name) { + super(assets, definitionsDir + "/" + name); + } + + /** * getAllFiles * Returns a list of the paths of all language definition files in the assets folder or an empty list on error. @@ -35,10 +39,7 @@ public class LanguageDefinition { public static ArrayList getAllFiles(AssetManager assets) { ArrayList files = new ArrayList<>(); try { - for (String file : assets.list(definitionsDir)) { - files.add(definitionsDir + "/" + file); - } - + files.addAll(Arrays.asList(assets.list(definitionsDir))); Logger.d("LanguageDefinition", "Found: " + files.size() + " languages."); } catch (IOException | NullPointerException e) { Logger.e("tt9.LanguageDefinition", "Failed reading language definitions from: '" + definitionsDir + "'. " + e.getMessage()); @@ -54,7 +55,9 @@ public class LanguageDefinition { * or throws an IOException on error. */ public static LanguageDefinition fromFile(AssetManager assetManager, String definitionFile) throws IOException { - return parse(load(assetManager, definitionFile)); + LanguageDefinition definition = new LanguageDefinition(assetManager, definitionFile); + definition.parse(definition.load(definition)); + return definition; } @@ -62,8 +65,8 @@ public class LanguageDefinition { * load * Loads a language definition file from the assets folder into a String or throws an IOException on error. */ - private static ArrayList load(AssetManager assetManager, String definitionFile) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open(definitionFile), StandardCharsets.UTF_8)); + private ArrayList load(LanguageDefinition definitionFile) throws IOException { + BufferedReader reader = definitionFile.getReader(); ArrayList fileContents = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { @@ -78,26 +81,25 @@ public class LanguageDefinition { * parse * Converts "yaml" to a LanguageDefinition object. All properties in the YAML are considered optional, * so the LanguageDefinition defaults will be used when some property is omitted. - * * Had to write all this, because the only usable library, SnakeYAML, works fine on Android 10+, * but causes crashes on older devices. */ - @NonNull - private static LanguageDefinition parse(ArrayList yaml) { - LanguageDefinition definition = new LanguageDefinition(); - definition.abcString = getPropertyFromYaml(yaml, "abcString", definition.abcString); - definition.dictionaryFile = getPropertyFromYaml(yaml, "dictionaryFile", definition.dictionaryFile); - definition.hasSpaceBetweenWords = getPropertyFromYaml(yaml, "hasSpaceBetweenWords", definition.hasSpaceBetweenWords); - definition.hasUpperCase = getPropertyFromYaml(yaml, "hasUpperCase", definition.hasUpperCase); - definition.layout = getLayoutFromYaml(yaml); - definition.locale = getPropertyFromYaml(yaml, "locale", definition.locale); - definition.name = getPropertyFromYaml(yaml, "name", definition.name); + private void parse(ArrayList yaml) { + abcString = getPropertyFromYaml(yaml, "abcString", abcString); - if (definition.dictionaryFile != null) { - definition.dictionaryFile = definition.dictionaryFile.replaceFirst("\\.\\w+$", "." + BuildConfig.DICTIONARY_EXTENSION); + dictionaryFile = getPropertyFromYaml(yaml, "dictionaryFile", dictionaryFile); + if (dictionaryFile != null) { + dictionaryFile = dictionaryFile.replaceFirst("\\.\\w+$", "." + BuildConfig.DICTIONARY_EXTENSION); } - return definition; + + hasSpaceBetweenWords = getPropertyFromYaml(yaml, "hasSpaceBetweenWords", hasSpaceBetweenWords); + hasUpperCase = getPropertyFromYaml(yaml, "hasUpperCase", hasUpperCase); + layout = getLayoutFromYaml(yaml); + locale = getPropertyFromYaml(yaml, "locale", locale); + name = getPropertyFromYaml(yaml, "name", name); + + } @@ -107,7 +109,7 @@ public class LanguageDefinition { * Optional properties are allowed. If the property is not found, "defaultValue" will be returned. */ @Nullable - private static String getPropertyFromYaml(ArrayList yaml, String property, String defaultValue) { + private String getPropertyFromYaml(ArrayList yaml, String property, String defaultValue) { for (String line : yaml) { line = line.replaceAll("#.+$", "").trim(); String[] parts = line.split(":"); @@ -128,7 +130,7 @@ public class LanguageDefinition { * The boolean variant of getPropertyFromYaml. It returns true if the property is found and is: * "true", "on", "yes" or "y". */ - private static boolean getPropertyFromYaml(ArrayList yaml, String property, boolean defaultValue) { + private boolean getPropertyFromYaml(ArrayList yaml, String property, boolean defaultValue) { String value = getPropertyFromYaml(yaml, property, null); if (value == null) { return defaultValue; @@ -144,7 +146,7 @@ public class LanguageDefinition { * Finds and extracts the keypad layout. Less than 10 keys are accepted allowed leaving the ones up to 9-key empty. */ @NonNull - private static ArrayList> getLayoutFromYaml(ArrayList yaml) { + private ArrayList> getLayoutFromYaml(ArrayList yaml) { ArrayList> layout = new ArrayList<>(); boolean inLayout = false; @@ -174,7 +176,7 @@ public class LanguageDefinition { * If the YAML line is invalid, NULL will be returned. */ @Nullable - private static ArrayList getLayoutEntryFromYamlLine(String yamlLine) { + private ArrayList getLayoutEntryFromYamlLine(String yamlLine) { if (!yamlLine.contains("[") || !yamlLine.contains("]")) { return null; } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/HelpActivity.java b/app/src/main/java/io/github/sspanak/tt9/preferences/HelpActivity.java index b7eb51a9..0f6a3cea 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/HelpActivity.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/HelpActivity.java @@ -1,12 +1,7 @@ package io.github.sspanak.tt9.preferences; -import android.content.res.AssetManager; - import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import io.github.sspanak.tt9.ui.WebViewActivity; import io.github.sspanak.tt9.util.Logger; @@ -21,8 +16,7 @@ public class HelpActivity extends WebViewActivity { @Override protected String getText() { try { - InputStream stream = getHelpFileStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); + BufferedReader reader = getHelpFileReader(); StringBuilder builder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { @@ -35,14 +29,10 @@ public class HelpActivity extends WebViewActivity { } } - private InputStream getHelpFileStream() throws IOException { - AssetManager assets = getAssets(); + private BufferedReader getHelpFileReader() throws IOException { String systemLanguage = SystemSettings.getLocale().replaceFirst("_\\w+$", ""); - - try { - return assets.open("help/help." + systemLanguage + ".html"); - } catch (IOException ignored) { - return assets.open("help/help.en.html"); - } + HelpFile file = new HelpFile(this, systemLanguage); + file = file.exists() ? file : new HelpFile(this); + return file.getReader(); } } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/HelpFile.java b/app/src/main/java/io/github/sspanak/tt9/preferences/HelpFile.java new file mode 100644 index 00000000..93a817bf --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/HelpFile.java @@ -0,0 +1,17 @@ +package io.github.sspanak.tt9.preferences; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import io.github.sspanak.tt9.util.AssetFile; + +public class HelpFile extends AssetFile { + public HelpFile(@NonNull Context context, String language) { + super(context.getAssets(), "help/help." + language + ".html"); + } + + public HelpFile(@NonNull Context context) { + super(context.getAssets(), "help/help.en.html"); + } +} diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/main/MainSettingsScreen.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/main/MainSettingsScreen.java index 767a6d3f..0a889294 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/main/MainSettingsScreen.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/main/MainSettingsScreen.java @@ -4,9 +4,9 @@ import androidx.preference.Preference; import java.util.ArrayList; import java.util.Arrays; -import java.util.Set; import io.github.sspanak.tt9.R; +import io.github.sspanak.tt9.preferences.HelpFile; import io.github.sspanak.tt9.preferences.PreferencesActivity; import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment; import io.github.sspanak.tt9.util.SystemSettings; @@ -53,7 +53,7 @@ public class MainSettingsScreen extends BaseScreenFragment { } String systemLanguage = SystemSettings.getLocale().replaceAll("_\\w+$", ""); - help.setSummary(Set.of("de", "en", "es", "it", "ru", "tr").contains(systemLanguage) ? "" : "English only"); + help.setSummary(new HelpFile(activity, systemLanguage).exists() ? "" : "English only"); } diff --git a/app/src/main/java/io/github/sspanak/tt9/util/AssetFile.java b/app/src/main/java/io/github/sspanak/tt9/util/AssetFile.java new file mode 100644 index 00000000..60e15070 --- /dev/null +++ b/app/src/main/java/io/github/sspanak/tt9/util/AssetFile.java @@ -0,0 +1,38 @@ +package io.github.sspanak.tt9.util; + +import android.content.res.AssetManager; + +import androidx.annotation.NonNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +public class AssetFile { + protected final AssetManager assets; + protected final String path; + + public AssetFile(@NonNull AssetManager assets, String path) { + this.assets = assets; + this.path = path; + } + + public boolean exists() { + try { + assets.open(path).close(); + return true; + } catch (IOException e) { + return false; + } + } + + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getStream(), StandardCharsets.UTF_8)); + } + + protected InputStream getStream() throws IOException { + return assets.open(path); + } +}