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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.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";
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class DictionaryProgressNotification extends DictionaryNotification {
|
|||
|
||||
|
||||
@Override
|
||||
protected void hide() {
|
||||
public void hide() {
|
||||
progress = maxProgress = 0;
|
||||
super.hide();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue