arblant
FoxyVPN-MultiAcc / app / src / main / java / com / vauth / foxyvpn / data / CrashReporter.kt
CrashReporter.kt48 lines · 1.6 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
package com.vauth.foxyvpn.data

import android.content.Context
import java.io.File
import java.io.PrintWriter
import java.io.StringWriter

object CrashReporter {
    private const val TAG = "CrashReporter"
    private const val CRASH_FILE_NAME = "last_crash.txt"

    fun install(context: Context) {
        val appContext = context.applicationContext
        val previousHandler = Thread.getDefaultUncaughtExceptionHandler()
        Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
            runCatching { writeCrashFile(appContext, thread, throwable) }

            if (previousHandler != null) {
                previousHandler.uncaughtException(thread, throwable)
            } else {
                Runtime.getRuntime().exit(1)
            }
        }
    }

    fun replayLastCrashIfAny(context: Context) {
        val file = crashFile(context)
        if (!file.exists()) return
        val text = runCatching { file.readText() }.getOrNull()
        runCatching { file.delete() }
        if (text.isNullOrBlank()) return
        AppLogger.e(TAG, "app crashed last run; captured stack trace follows")
        text.lineSequence().forEach { line ->
            if (line.isNotBlank()) AppLogger.e(TAG, line)
        }
    }

    private fun writeCrashFile(context: Context, thread: Thread, throwable: Throwable) {
        val writer = StringWriter()
        PrintWriter(writer).use { pw ->
            pw.println("Thread: ${thread.name}")
            throwable.printStackTrace(pw)
        }
        crashFile(context).writeText(writer.toString())
    }

    private fun crashFile(context: Context): File = File(context.filesDir, CRASH_FILE_NAME)
}