1
0
Fork 0

added a Logcat Exporter debugging tool

This commit is contained in:
sspanak 2024-04-16 13:07:21 +03:00 committed by Dimo Karaivanov
parent 3d1b1cd6ff
commit 7f402d370e
12 changed files with 160 additions and 43 deletions

View file

@ -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;
}

View file

@ -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");

View file

@ -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");

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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);
}
});
}
}

View file

@ -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";

View file

@ -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";

View file

@ -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);
}

View file

@ -68,7 +68,7 @@ public class DictionaryProgressNotification extends DictionaryNotification {
@Override
protected void hide() {
public void hide() {
progress = maxProgress = 0;
super.hide();
}

View file

@ -30,6 +30,11 @@
app:layout="@layout/pref_switch"
app:title="System Logs" />
<Preference
app:key="pref_export_logcat"
app:layout="@layout/pref_text"
app:title="Export Logs" />
<PreferenceCategory
app:title="Recent Log Messages"
app:layout="@layout/pref_category"