@@ -16,7 +16,7 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.preferences_main, rootKey);
- final var about = findPreference("about");
+ final var about = findPreference("about2");
final var connection = findPreference("connection");
if (about == null || connection == null) {
throw new IllegalStateException(
@@ -1,36 +1,59 @@
package eu.siacs.conversations.utils;
import android.content.Context;
+import android.os.Build;
import androidx.annotation.NonNull;
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+import eu.siacs.conversations.BuildConfig;
+import eu.siacs.conversations.services.NotificationService;
+
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
-
-import eu.siacs.conversations.services.NotificationService;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
public class ExceptionHandler implements UncaughtExceptionHandler {
- private final UncaughtExceptionHandler defaultHandler;
- private final Context context;
-
- ExceptionHandler(final Context context) {
- this.context = context;
- this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
- }
-
- @Override
- public void uncaughtException(@NonNull Thread thread, final Throwable throwable) {
- NotificationService.cancelIncomingCallNotification(context);
- final Writer stringWriter = new StringWriter();
- final PrintWriter printWriter = new PrintWriter(stringWriter);
- throwable.printStackTrace(printWriter);
- final String stacktrace = stringWriter.toString();
- printWriter.close();
- ExceptionHelper.writeToStacktraceFile(context, stacktrace);
- this.defaultHandler.uncaughtException(thread, throwable);
- }
-
+ private static final SimpleDateFormat DATE_FORMAT =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.ENGLISH);
+
+ private final UncaughtExceptionHandler defaultHandler;
+ private final Context context;
+
+ ExceptionHandler(final Context context) {
+ this.context = context;
+ this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ }
+
+ @Override
+ public void uncaughtException(@NonNull Thread thread, final Throwable throwable) {
+ NotificationService.cancelIncomingCallNotification(context);
+ final String stacktrace;
+ try (final StringWriter stringWriter = new StringWriter();
+ final PrintWriter printWriter = new PrintWriter(stringWriter)) {
+ throwable.printStackTrace(printWriter);
+ stacktrace = stringWriter.toString();
+ } catch (final IOException e) {
+ return;
+ }
+ final List<String> report =
+ ImmutableList.of(
+ String.format(
+ "Version: %s %s", BuildConfig.APP_NAME, BuildConfig.VERSION_NAME),
+ String.format("Manufacturer: %s", Strings.nullToEmpty(Build.MANUFACTURER)),
+ String.format("Device: %s", Strings.nullToEmpty(Build.DEVICE)),
+ String.format("Timestamp: %s", DATE_FORMAT.format(new Date())),
+ stacktrace);
+ ExceptionHelper.writeToStacktraceFile(context, Joiner.on("\n").join(report));
+ this.defaultHandler.uncaughtException(thread, throwable);
+ }
}
@@ -1,12 +1,12 @@
package eu.siacs.conversations.utils;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
import android.util.Log;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+import com.google.common.base.Charsets;
+import com.google.common.io.CharSink;
+import com.google.common.io.Files;
import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
@@ -17,19 +17,15 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.XmppActivity;
-import java.io.BufferedReader;
-import java.io.FileInputStream;
+import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
-import java.util.Date;
import java.util.Locale;
public class ExceptionHelper {
private static final String FILENAME = "stacktrace.txt";
- private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
public static void init(final Context context) {
if (Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler) {
@@ -39,72 +35,65 @@ public class ExceptionHelper {
}
public static boolean checkForCrash(final XmppActivity activity) {
+ final XmppConnectionService service =
+ activity == null ? null : activity.xmppConnectionService;
+ if (service == null) {
+ return false;
+ }
+ final AppSettings appSettings = new AppSettings(activity);
+ if (!appSettings.isSendCrashReports() || Config.BUG_REPORTS == null) {
+ return false;
+ }
+ final Account account = AccountUtils.getFirstEnabled(service);
+ if (account == null) {
+ return false;
+ }
+ final var file = new File(activity.getCacheDir(), FILENAME);
+ if (!file.exists()) {
+ return false;
+ }
+ final String report;
try {
- final XmppConnectionService service = activity == null ? null : activity.xmppConnectionService;
- if (service == null) {
- return false;
- }
- final AppSettings appSettings = new AppSettings(activity);
- if (!appSettings.isSendCrashReports() || Config.BUG_REPORTS == null) {
- return false;
- }
- final Account account = AccountUtils.getFirstEnabled(service);
- if (account == null) {
- return false;
- }
- final FileInputStream file = activity.openFileInput(FILENAME);
- final InputStreamReader inputStreamReader = new InputStreamReader(file);
- final BufferedReader stacktrace = new BufferedReader(inputStreamReader);
- final StringBuilder report = new StringBuilder();
- final PackageManager pm = activity.getPackageManager();
- final PackageInfo packageInfo;
- try {
- packageInfo = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_SIGNATURES);
- final String versionName = packageInfo.versionName;
- final int versionCode = packageInfo.versionCode;
- final int version = versionCode > 10000 ? (versionCode / 100) : versionCode;
- report.append(String.format(Locale.ROOT, "Version: %s(%d)", versionName, version)).append('\n');
- report.append("Last Update: ").append(DATE_FORMAT.format(new Date(packageInfo.lastUpdateTime))).append('\n');
- Signature[] signatures = packageInfo.signatures;
- if (signatures != null && signatures.length >= 1) {
- report.append("SHA-1: ").append(CryptoHelper.getFingerprintCert(packageInfo.signatures[0].toByteArray())).append('\n');
- }
- report.append('\n');
- } catch (final Exception e) {
- return false;
- }
- String line;
- while ((line = stacktrace.readLine()) != null) {
- report.append(line);
- report.append('\n');
- }
- file.close();
- activity.deleteFile(FILENAME);
- final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity);
- builder.setTitle(activity.getString(R.string.crash_report_title, activity.getString(R.string.app_name)));
- builder.setMessage(activity.getString(R.string.crash_report_message, activity.getString(R.string.app_name)));
- builder.setPositiveButton(activity.getText(R.string.send_now), (dialog, which) -> {
-
- Log.d(Config.LOGTAG, "using account=" + account.getJid().asBareJid() + " to send in stack trace");
- Conversation conversation = service.findOrCreateConversation(account, Config.BUG_REPORTS, false, true);
- Message message = new Message(conversation, report.toString(), Message.ENCRYPTION_NONE);
- service.sendMessage(message);
- });
- builder.setNegativeButton(activity.getText(R.string.send_never), (dialog, which) -> appSettings.setSendCrashReports(false));
- builder.create().show();
- return true;
- } catch (final IOException ignored) {
+ report = Files.asCharSource(file, Charsets.UTF_8).read();
+ } catch (final IOException e) {
return false;
}
+ if (file.delete()) {
+ Log.d(Config.LOGTAG, "deleted crash report file");
+ }
+ final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity);
+ builder.setTitle(
+ activity.getString(
+ R.string.crash_report_title, activity.getString(R.string.app_name)));
+ builder.setMessage(
+ activity.getString(
+ R.string.crash_report_message, activity.getString(R.string.app_name)));
+ builder.setPositiveButton(
+ activity.getText(R.string.send_now),
+ (dialog, which) -> {
+ Log.d(
+ Config.LOGTAG,
+ "using account="
+ + account.getJid().asBareJid()
+ + " to send in stack trace");
+ Conversation conversation =
+ service.findOrCreateConversation(
+ account, Config.BUG_REPORTS, false, true);
+ Message message = new Message(conversation, report, Message.ENCRYPTION_NONE);
+ service.sendMessage(message);
+ });
+ builder.setNegativeButton(
+ activity.getText(R.string.send_never),
+ (dialog, which) -> appSettings.setSendCrashReports(false));
+ builder.create().show();
+ return true;
}
- static void writeToStacktraceFile(Context context, String msg) {
+ static void writeToStacktraceFile(final Context context, final String msg) {
try {
- OutputStream os = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
- os.write(msg.getBytes());
- os.flush();
- os.close();
- } catch (IOException ignored) {
+ Files.asCharSink(new File(context.getCacheDir(), FILENAME), Charsets.UTF_8).write(msg);
+ } catch (IOException e) {
+ Log.w(Config.LOGTAG, "could not write stack trace to file", e);
}
}
}