diff --git a/app/src/main/java/io/github/sspanak/tt9/db/exporter/AbstractExporter.java b/app/src/main/java/io/github/sspanak/tt9/db/exporter/AbstractExporter.java
index a97b5734..cf5ddeff 100644
--- a/app/src/main/java/io/github/sspanak/tt9/db/exporter/AbstractExporter.java
+++ b/app/src/main/java/io/github/sspanak/tt9/db/exporter/AbstractExporter.java
@@ -21,8 +21,8 @@ import java.io.OutputStream;
import io.github.sspanak.tt9.util.ConsumerCompat;
public abstract class AbstractExporter {
- final protected static String FILE_EXTENSION = ".csv";
- final protected static String MIME_TYPE = "text/csv";
+ protected static String FILE_EXTENSION = ".csv";
+ protected static String MIME_TYPE = "text/csv";
protected Runnable failureHandler;
protected Runnable startHandler;
@@ -54,7 +54,7 @@ public abstract class AbstractExporter {
if (stream == null) {
throw new IOException("Failed to open output stream.");
}
- stream.write(getWords(activity));
+ stream.write(getFileContents(activity));
}
} catch (IOException e) {
if (uri != null) {
@@ -84,7 +84,7 @@ public abstract class AbstractExporter {
}
try (OutputStream stream = new FileOutputStream(file)) {
- stream.write(getWords(activity));
+ stream.write(getFileContents(activity));
}
MediaScannerConnection.scanFile(activity, new String[]{file.getAbsolutePath()}, new String[]{MIME_TYPE}, null);
@@ -163,5 +163,5 @@ public abstract class AbstractExporter {
abstract protected void exportSync(Activity activity);
@NonNull abstract protected String generateFileName();
- @NonNull abstract protected byte[] getWords(Activity activity) throws Exception;
+ @NonNull abstract protected byte[] getFileContents(Activity activity) throws Exception;
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/db/exporter/CustomWordsExporter.java b/app/src/main/java/io/github/sspanak/tt9/db/exporter/CustomWordsExporter.java
index f270309f..bf771331 100644
--- a/app/src/main/java/io/github/sspanak/tt9/db/exporter/CustomWordsExporter.java
+++ b/app/src/main/java/io/github/sspanak/tt9/db/exporter/CustomWordsExporter.java
@@ -41,7 +41,7 @@ public class CustomWordsExporter extends AbstractExporter {
@NonNull
@Override
- protected byte[] getWords(Activity activity) throws Exception {
+ protected byte[] getFileContents(Activity activity) throws Exception {
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
if (db == null) {
throw new Exception("Could not open database");
diff --git a/app/src/main/java/io/github/sspanak/tt9/db/exporter/DictionaryExporter.java b/app/src/main/java/io/github/sspanak/tt9/db/exporter/DictionaryExporter.java
index 2644dff0..35204a57 100644
--- a/app/src/main/java/io/github/sspanak/tt9/db/exporter/DictionaryExporter.java
+++ b/app/src/main/java/io/github/sspanak/tt9/db/exporter/DictionaryExporter.java
@@ -7,12 +7,12 @@ import androidx.annotation.NonNull;
import java.util.ArrayList;
-import io.github.sspanak.tt9.util.Logger;
import io.github.sspanak.tt9.R;
-import io.github.sspanak.tt9.util.Timer;
import io.github.sspanak.tt9.db.sqlite.ReadOps;
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
import io.github.sspanak.tt9.languages.Language;
+import io.github.sspanak.tt9.util.Logger;
+import io.github.sspanak.tt9.util.Timer;
public class DictionaryExporter extends AbstractExporter {
private static DictionaryExporter self;
@@ -62,7 +62,7 @@ public class DictionaryExporter extends AbstractExporter {
@Override
@NonNull
- protected byte[] getWords(Activity activity) throws Exception {
+ protected byte[] getFileContents(Activity activity) throws Exception {
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
if (db == null) {
throw new Exception("Could not open database");
diff --git a/app/src/main/java/io/github/sspanak/tt9/db/exporter/LogcatExporter.java b/app/src/main/java/io/github/sspanak/tt9/db/exporter/LogcatExporter.java
new file mode 100644
index 00000000..c9c1d91c
--- /dev/null
+++ b/app/src/main/java/io/github/sspanak/tt9/db/exporter/LogcatExporter.java
@@ -0,0 +1,85 @@
+package io.github.sspanak.tt9.db.exporter;
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import io.github.sspanak.tt9.util.Logger;
+
+public class LogcatExporter extends AbstractExporter {
+ private static LogcatExporter self;
+ private final String BASE_FILE_NAME;
+ private boolean includeSystemLogs;
+
+
+ public LogcatExporter() {
+ super();
+ BASE_FILE_NAME = "tt9-logs-";
+ FILE_EXTENSION = ".txt";
+ MIME_TYPE = "text/plain";
+ }
+
+
+ public static LogcatExporter getInstance() {
+ if (self == null) {
+ self = new LogcatExporter();
+ }
+ return self;
+ }
+
+
+ public static String getLogs(boolean includeSystemLogs) {
+ StringBuilder log = new StringBuilder();
+ try {
+ Process process = Runtime.getRuntime().exec("logcat -d -v threadtime io.github.sspanak.tt9:D");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ if (includeSystemLogs || line.contains(Logger.TAG_PREFIX)) {
+ log.append(line).append("\n");
+ }
+ }
+ } catch (IOException e) {
+ log.append("Error getting the logs. ").append(e.getMessage());
+ }
+
+ return log.toString();
+ }
+
+
+ public LogcatExporter setIncludeSystemLogs(boolean includeSystemLogs) {
+ this.includeSystemLogs = includeSystemLogs;
+ return this;
+ }
+
+
+ @Override
+ protected void exportSync(Activity activity) {
+ try {
+ sendStart("Exporting logs...");
+ write(activity);
+ sendSuccess();
+ } catch (Exception e) {
+ sendFailure();
+ }
+ }
+
+
+ @NonNull
+ @Override
+ protected String generateFileName() {
+ return BASE_FILE_NAME + System.currentTimeMillis() + FILE_EXTENSION;
+ }
+
+
+ @NonNull
+ @Override
+ protected byte[] getFileContents(Activity activity) {
+ return getLogs(includeSystemLogs).getBytes();
+ }
+}
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportAbstract.java b/app/src/main/java/io/github/sspanak/tt9/preferences/items/ItemExportAbstract.java
similarity index 87%
rename from app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportAbstract.java
rename to app/src/main/java/io/github/sspanak/tt9/preferences/items/ItemExportAbstract.java
index e6d7234f..4f8985df 100644
--- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportAbstract.java
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/items/ItemExportAbstract.java
@@ -1,19 +1,18 @@
-package io.github.sspanak.tt9.preferences.screens.languages;
+package io.github.sspanak.tt9.preferences.items;
import androidx.preference.Preference;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.exporter.AbstractExporter;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
-import io.github.sspanak.tt9.preferences.items.ItemClickable;
import io.github.sspanak.tt9.ui.notifications.DictionaryProgressNotification;
-abstract class ItemExportAbstract extends ItemClickable {
+abstract public class ItemExportAbstract extends ItemClickable {
final protected PreferencesActivity activity;
final private Runnable onStart;
final private Runnable onFinish;
- ItemExportAbstract(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
+ public ItemExportAbstract(Preference item, PreferencesActivity activity, Runnable onStart, Runnable onFinish) {
super(item);
this.activity = activity;
this.onStart = onStart;
@@ -75,7 +74,7 @@ abstract class ItemExportAbstract extends ItemClickable {
protected void setLoadingStatus() {
- onStart.run();
+ if (onStart != null) onStart.run();
disable();
String loadingMessage = getExporter().getStatusMessage();
@@ -86,6 +85,6 @@ abstract class ItemExportAbstract extends ItemClickable {
public void setReadyStatus() {
enable();
- onFinish.run();
+ if (onFinish != null) onFinish.run();
}
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/DebugScreen.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/DebugScreen.java
index 4773d79a..ac7203a3 100644
--- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/DebugScreen.java
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/DebugScreen.java
@@ -2,16 +2,12 @@ package io.github.sspanak.tt9.preferences.screens.debug;
import androidx.preference.SwitchPreferenceCompat;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
import io.github.sspanak.tt9.R;
+import io.github.sspanak.tt9.db.exporter.LogcatExporter;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
import io.github.sspanak.tt9.preferences.items.ItemText;
import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
import io.github.sspanak.tt9.util.DeviceInfo;
-import io.github.sspanak.tt9.util.Logger;
public class DebugScreen extends BaseScreenFragment {
public static final String NAME = "Debug";
@@ -34,6 +30,7 @@ public class DebugScreen extends BaseScreenFragment {
(new ItemLogLevel(findPreference(ItemLogLevel.NAME))).populate().preview().enableClickHandler();
(new ItemInputHandlingMode(findPreference(ItemInputHandlingMode.NAME), activity.getSettings())).populate().preview().enableClickHandler();
(new ItemText(activity, findPreference(DEVICE_INFO_CONTAINER))).populate(new DeviceInfo().toString()).enableClickHandler();
+ (new ItemExportLogcat(findPreference(ItemExportLogcat.NAME), activity)).enableClickHandler();
initSystemLogsSwitch();
SwitchPreferenceCompat systemLogs = findPreference(SYSTEM_LOGS_SWITCH);
@@ -52,30 +49,15 @@ public class DebugScreen extends BaseScreenFragment {
}
private void printLogs(boolean includeSystemLogs) {
- StringBuilder log = new StringBuilder();
- try {
- Process process = Runtime.getRuntime().exec("logcat -d -v threadtime io.github.sspanak.tt9:D");
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
-
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- if (includeSystemLogs || line.contains(Logger.TAG_PREFIX)) {
- log.append(line).append("\n\n");
- }
- }
- }
- catch (IOException e) {
- log.append("Error getting the logs. ").append(e.getMessage());
- }
-
- if (log.toString().isEmpty()) {
- log.append("No Logs");
- }
-
if (logsContainer == null) {
logsContainer = new ItemText(activity, findPreference("debug_logs_container"));
logsContainer.enableClickHandler();
}
- logsContainer.populate(log.toString());
+
+ String logs = LogcatExporter.getLogs(includeSystemLogs).replace("\n", "\n\n");
+ if (logs.isEmpty()) {
+ logs = "No Logs";
+ }
+ logsContainer.populate(logs);
}
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/ItemExportLogcat.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/ItemExportLogcat.java
new file mode 100644
index 00000000..3aaa9e8a
--- /dev/null
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/debug/ItemExportLogcat.java
@@ -0,0 +1,40 @@
+package io.github.sspanak.tt9.preferences.screens.debug;
+
+import androidx.preference.Preference;
+
+import io.github.sspanak.tt9.db.exporter.LogcatExporter;
+import io.github.sspanak.tt9.preferences.PreferencesActivity;
+import io.github.sspanak.tt9.preferences.items.ItemExportAbstract;
+import io.github.sspanak.tt9.ui.notifications.DictionaryProgressNotification;
+
+public class ItemExportLogcat extends ItemExportAbstract {
+ public static final String NAME = "pref_export_logcat";
+
+ public ItemExportLogcat(Preference item, PreferencesActivity activity) {
+ super(item, activity, null, null);
+ }
+
+ @Override
+ protected LogcatExporter getExporter() {
+ return LogcatExporter.getInstance();
+ }
+
+ @Override
+ protected boolean onStartExporting() {
+ return getExporter().setIncludeSystemLogs(activity.getSettings().getEnableSystemLogs()).export(activity);
+ }
+
+ @Override
+ protected void onFinishExporting(String outputFile) {
+ activity.runOnUiThread(() -> {
+ DictionaryProgressNotification.getInstance(activity).hide();
+ setReadyStatus();
+
+ if (outputFile == null) {
+ item.setSummary("Export failed");
+ } else {
+ item.setSummary("Logs exported to: " + outputFile);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportCustomWords.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportCustomWords.java
index e1b44b7e..213d270f 100644
--- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportCustomWords.java
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportCustomWords.java
@@ -5,6 +5,7 @@ import androidx.preference.Preference;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.exporter.CustomWordsExporter;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
+import io.github.sspanak.tt9.preferences.items.ItemExportAbstract;
class ItemExportCustomWords extends ItemExportAbstract {
final public static String NAME = "dictionary_export_custom";
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportDictionary.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportDictionary.java
index cfbccd63..5dd98486 100644
--- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportDictionary.java
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemExportDictionary.java
@@ -2,10 +2,11 @@ package io.github.sspanak.tt9.preferences.screens.languages;
import androidx.preference.Preference;
-import io.github.sspanak.tt9.util.Logger;
import io.github.sspanak.tt9.db.exporter.DictionaryExporter;
import io.github.sspanak.tt9.languages.LanguageCollection;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
+import io.github.sspanak.tt9.preferences.items.ItemExportAbstract;
+import io.github.sspanak.tt9.util.Logger;
class ItemExportDictionary extends ItemExportAbstract {
final public static String NAME = "dictionary_export";
diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsHacks.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsHacks.java
index baccec0d..b13c8a4d 100644
--- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsHacks.java
+++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsHacks.java
@@ -14,6 +14,10 @@ class SettingsHacks extends BaseSettings {
return getStringifiedInt("pref_log_level", Logger.LEVEL);
}
+ public boolean getEnableSystemLogs() {
+ return prefs.getBoolean("pref_enable_system_logs", false);
+ }
+
public int getInputHandlingMode() {
return getStringifiedInt("pref_input_handling_mode", ItemInputHandlingMode.NORMAL);
}
diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/notifications/DictionaryProgressNotification.java b/app/src/main/java/io/github/sspanak/tt9/ui/notifications/DictionaryProgressNotification.java
index 9e550046..e2ffc2e8 100644
--- a/app/src/main/java/io/github/sspanak/tt9/ui/notifications/DictionaryProgressNotification.java
+++ b/app/src/main/java/io/github/sspanak/tt9/ui/notifications/DictionaryProgressNotification.java
@@ -68,7 +68,7 @@ public class DictionaryProgressNotification extends DictionaryNotification {
@Override
- protected void hide() {
+ public void hide() {
progress = maxProgress = 0;
super.hide();
}
diff --git a/app/src/main/res/xml/prefs_screen_debug.xml b/app/src/main/res/xml/prefs_screen_debug.xml
index 1578d6a0..6bb38f27 100644
--- a/app/src/main/res/xml/prefs_screen_debug.xml
+++ b/app/src/main/res/xml/prefs_screen_debug.xml
@@ -30,6 +30,11 @@
app:layout="@layout/pref_switch"
app:title="System Logs" />
+
+