From fc2c7947870f2761652b10b3170fd3b0fc89c88a Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 15 Mar 2026 08:36:44 +0000 Subject: feat: add file-based crash logger for offline diagnostics NavApplication installs an UncaughtExceptionHandler that writes crash stack traces to crash_latest.txt (and timestamped copies) in the app's external files dir. Readable without root or ADB. Co-Authored-By: Claude Sonnet 4.6 --- android-app/app/src/main/AndroidManifest.xml | 1 + .../main/kotlin/org/terst/nav/NavApplication.kt | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 android-app/app/src/main/kotlin/org/terst/nav/NavApplication.kt diff --git a/android-app/app/src/main/AndroidManifest.xml b/android-app/app/src/main/AndroidManifest.xml index 0b9fc05..e3d679b 100644 --- a/android-app/app/src/main/AndroidManifest.xml +++ b/android-app/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ + try { + writeCrashLog(thread, throwable) + } catch (_: Exception) { + // never suppress the original crash + } + default?.uncaughtException(thread, throwable) + } + } + + private fun writeCrashLog(thread: Thread, throwable: Throwable) { + val sw = StringWriter() + throwable.printStackTrace(PrintWriter(sw)) + val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date()) + val body = buildString { + appendLine("=== Nav Crash Log ===") + appendLine("Time : $timestamp") + appendLine("Thread : ${thread.name}") + appendLine("Device : ${android.os.Build.MODEL} (API ${android.os.Build.VERSION.SDK_INT})") + appendLine() + append(sw) + } + + // Try external storage first (readable without root) + val dir = getExternalFilesDir(null) ?: filesDir + val file = File(dir, "crash_${timestamp}.txt") + file.writeText(body) + + // Also overwrite a fixed-name "latest" file for easy access + File(dir, "crash_latest.txt").writeText(body) + } +} -- cgit v1.2.3