added a Logcat Exporter debugging tool
This commit is contained in:
parent
3d1b1cd6ff
commit
7f402d370e
12 changed files with 160 additions and 43 deletions
|
|
@ -21,8 +21,8 @@ import java.io.OutputStream;
|
||||||
import io.github.sspanak.tt9.util.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
|
|
||||||
public abstract class AbstractExporter {
|
public abstract class AbstractExporter {
|
||||||
final protected static String FILE_EXTENSION = ".csv";
|
protected static String FILE_EXTENSION = ".csv";
|
||||||
final protected static String MIME_TYPE = "text/csv";
|
protected static String MIME_TYPE = "text/csv";
|
||||||
|
|
||||||
protected Runnable failureHandler;
|
protected Runnable failureHandler;
|
||||||
protected Runnable startHandler;
|
protected Runnable startHandler;
|
||||||
|
|
@ -54,7 +54,7 @@ public abstract class AbstractExporter {
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
throw new IOException("Failed to open output stream.");
|
throw new IOException("Failed to open output stream.");
|
||||||
}
|
}
|
||||||
stream.write(getWords(activity));
|
stream.write(getFileContents(activity));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
|
|
@ -84,7 +84,7 @@ public abstract class AbstractExporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
try (OutputStream stream = new FileOutputStream(file)) {
|
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);
|
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);
|
abstract protected void exportSync(Activity activity);
|
||||||
@NonNull abstract protected String generateFileName();
|
@NonNull abstract protected String generateFileName();
|
||||||
@NonNull abstract protected byte[] getWords(Activity activity) throws Exception;
|
@NonNull abstract protected byte[] getFileContents(Activity activity) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public class CustomWordsExporter extends AbstractExporter {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected byte[] getWords(Activity activity) throws Exception {
|
protected byte[] getFileContents(Activity activity) throws Exception {
|
||||||
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
|
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
|
||||||
if (db == null) {
|
if (db == null) {
|
||||||
throw new Exception("Could not open database");
|
throw new Exception("Could not open database");
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
|
||||||
import io.github.sspanak.tt9.R;
|
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.ReadOps;
|
||||||
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
|
import io.github.sspanak.tt9.db.sqlite.SQLiteOpener;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
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 {
|
public class DictionaryExporter extends AbstractExporter {
|
||||||
private static DictionaryExporter self;
|
private static DictionaryExporter self;
|
||||||
|
|
@ -62,7 +62,7 @@ public class DictionaryExporter extends AbstractExporter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
protected byte[] getWords(Activity activity) throws Exception {
|
protected byte[] getFileContents(Activity activity) throws Exception {
|
||||||
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
|
SQLiteDatabase db = SQLiteOpener.getInstance(activity).getDb();
|
||||||
if (db == null) {
|
if (db == null) {
|
||||||
throw new Exception("Could not open database");
|
throw new Exception("Could not open database");
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
package io.github.sspanak.tt9.preferences.screens.languages;
|
package io.github.sspanak.tt9.preferences.items;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.exporter.AbstractExporter;
|
import io.github.sspanak.tt9.db.exporter.AbstractExporter;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.items.ItemClickable;
|
|
||||||
import io.github.sspanak.tt9.ui.notifications.DictionaryProgressNotification;
|
import io.github.sspanak.tt9.ui.notifications.DictionaryProgressNotification;
|
||||||
|
|
||||||
abstract class ItemExportAbstract extends ItemClickable {
|
abstract public class ItemExportAbstract extends ItemClickable {
|
||||||
final protected PreferencesActivity activity;
|
final protected PreferencesActivity activity;
|
||||||
final private Runnable onStart;
|
final private Runnable onStart;
|
||||||
final private Runnable onFinish;
|
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);
|
super(item);
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
this.onStart = onStart;
|
this.onStart = onStart;
|
||||||
|
|
@ -75,7 +74,7 @@ abstract class ItemExportAbstract extends ItemClickable {
|
||||||
|
|
||||||
|
|
||||||
protected void setLoadingStatus() {
|
protected void setLoadingStatus() {
|
||||||
onStart.run();
|
if (onStart != null) onStart.run();
|
||||||
disable();
|
disable();
|
||||||
|
|
||||||
String loadingMessage = getExporter().getStatusMessage();
|
String loadingMessage = getExporter().getStatusMessage();
|
||||||
|
|
@ -86,6 +85,6 @@ abstract class ItemExportAbstract extends ItemClickable {
|
||||||
|
|
||||||
public void setReadyStatus() {
|
public void setReadyStatus() {
|
||||||
enable();
|
enable();
|
||||||
onFinish.run();
|
if (onFinish != null) onFinish.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,16 +2,12 @@ package io.github.sspanak.tt9.preferences.screens.debug;
|
||||||
|
|
||||||
import androidx.preference.SwitchPreferenceCompat;
|
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.R;
|
||||||
|
import io.github.sspanak.tt9.db.exporter.LogcatExporter;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
import io.github.sspanak.tt9.preferences.items.ItemText;
|
import io.github.sspanak.tt9.preferences.items.ItemText;
|
||||||
import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
|
import io.github.sspanak.tt9.preferences.screens.BaseScreenFragment;
|
||||||
import io.github.sspanak.tt9.util.DeviceInfo;
|
import io.github.sspanak.tt9.util.DeviceInfo;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
|
||||||
|
|
||||||
public class DebugScreen extends BaseScreenFragment {
|
public class DebugScreen extends BaseScreenFragment {
|
||||||
public static final String NAME = "Debug";
|
public static final String NAME = "Debug";
|
||||||
|
|
@ -34,6 +30,7 @@ public class DebugScreen extends BaseScreenFragment {
|
||||||
(new ItemLogLevel(findPreference(ItemLogLevel.NAME))).populate().preview().enableClickHandler();
|
(new ItemLogLevel(findPreference(ItemLogLevel.NAME))).populate().preview().enableClickHandler();
|
||||||
(new ItemInputHandlingMode(findPreference(ItemInputHandlingMode.NAME), activity.getSettings())).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 ItemText(activity, findPreference(DEVICE_INFO_CONTAINER))).populate(new DeviceInfo().toString()).enableClickHandler();
|
||||||
|
(new ItemExportLogcat(findPreference(ItemExportLogcat.NAME), activity)).enableClickHandler();
|
||||||
initSystemLogsSwitch();
|
initSystemLogsSwitch();
|
||||||
|
|
||||||
SwitchPreferenceCompat systemLogs = findPreference(SYSTEM_LOGS_SWITCH);
|
SwitchPreferenceCompat systemLogs = findPreference(SYSTEM_LOGS_SWITCH);
|
||||||
|
|
@ -52,30 +49,15 @@ public class DebugScreen extends BaseScreenFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printLogs(boolean includeSystemLogs) {
|
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) {
|
if (logsContainer == null) {
|
||||||
logsContainer = new ItemText(activity, findPreference("debug_logs_container"));
|
logsContainer = new ItemText(activity, findPreference("debug_logs_container"));
|
||||||
logsContainer.enableClickHandler();
|
logsContainer.enableClickHandler();
|
||||||
}
|
}
|
||||||
logsContainer.populate(log.toString());
|
|
||||||
|
String logs = LogcatExporter.getLogs(includeSystemLogs).replace("\n", "\n\n");
|
||||||
|
if (logs.isEmpty()) {
|
||||||
|
logs = "No Logs";
|
||||||
|
}
|
||||||
|
logsContainer.populate(logs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.preference.Preference;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.exporter.CustomWordsExporter;
|
import io.github.sspanak.tt9.db.exporter.CustomWordsExporter;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
||||||
|
import io.github.sspanak.tt9.preferences.items.ItemExportAbstract;
|
||||||
|
|
||||||
class ItemExportCustomWords extends ItemExportAbstract {
|
class ItemExportCustomWords extends ItemExportAbstract {
|
||||||
final public static String NAME = "dictionary_export_custom";
|
final public static String NAME = "dictionary_export_custom";
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ package io.github.sspanak.tt9.preferences.screens.languages;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
|
||||||
import io.github.sspanak.tt9.db.exporter.DictionaryExporter;
|
import io.github.sspanak.tt9.db.exporter.DictionaryExporter;
|
||||||
import io.github.sspanak.tt9.languages.LanguageCollection;
|
import io.github.sspanak.tt9.languages.LanguageCollection;
|
||||||
import io.github.sspanak.tt9.preferences.PreferencesActivity;
|
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 {
|
class ItemExportDictionary extends ItemExportAbstract {
|
||||||
final public static String NAME = "dictionary_export";
|
final public static String NAME = "dictionary_export";
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ class SettingsHacks extends BaseSettings {
|
||||||
return getStringifiedInt("pref_log_level", Logger.LEVEL);
|
return getStringifiedInt("pref_log_level", Logger.LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getEnableSystemLogs() {
|
||||||
|
return prefs.getBoolean("pref_enable_system_logs", false);
|
||||||
|
}
|
||||||
|
|
||||||
public int getInputHandlingMode() {
|
public int getInputHandlingMode() {
|
||||||
return getStringifiedInt("pref_input_handling_mode", ItemInputHandlingMode.NORMAL);
|
return getStringifiedInt("pref_input_handling_mode", ItemInputHandlingMode.NORMAL);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public class DictionaryProgressNotification extends DictionaryNotification {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void hide() {
|
public void hide() {
|
||||||
progress = maxProgress = 0;
|
progress = maxProgress = 0;
|
||||||
super.hide();
|
super.hide();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@
|
||||||
app:layout="@layout/pref_switch"
|
app:layout="@layout/pref_switch"
|
||||||
app:title="System Logs" />
|
app:title="System Logs" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="pref_export_logcat"
|
||||||
|
app:layout="@layout/pref_text"
|
||||||
|
app:title="Export Logs" />
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
app:title="Recent Log Messages"
|
app:title="Recent Log Messages"
|
||||||
app:layout="@layout/pref_category"
|
app:layout="@layout/pref_category"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue