package invalid.lena.scrcpy; import android.content.Context; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; // Catches uncaught exceptions on any thread, writes them as plain // text to /crash-.log, then chains to // the system default handler so the OS crash dialog still appears. // Testers can share the file from the app's storage instead of // fishing for it in adb logcat. public final class Crashlog { private Crashlog() {} public static void install(Context ctx) { File dir = ctx.getExternalFilesDir(null); if (dir == null) { Log.w("crashlog: no external storage, skipping install"); return; } Thread.UncaughtExceptionHandler prev = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler((t, e) -> { try { String ts = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.ROOT).format(new Date()); File out = new File(dir, "crash-" + ts + ".log"); try (PrintWriter pw = new PrintWriter(new FileWriter(out))) { pw.println("# " + new Date()); pw.println("# thread=" + t.getName()); pw.println(); e.printStackTrace(pw); } Log.e(e, "crashlog: wrote %s", out.getAbsolutePath()); } catch (Throwable ignored) { // best effort - do not mask the original crash } if (prev != null) prev.uncaughtException(t, e); }); Log.i("crashlog: installed -> %s", dir.getAbsolutePath()); } }