Android崩潰日誌記錄Kotlin版

import android.content.Context
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import java.io.*
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList

class MyCrashHandler(private val context: Context) : Thread.UncaughtExceptionHandler {

    private val TAG = MyCrashHandler::class.java.simpleName

    private val logFilePath =
        Environment.getExternalStorageDirectory().path + File.separator + Utils.getPackageName(
            context
        ) + File.separator + "Log" + File.separator + "crashlog"

    override fun uncaughtException(t: Thread, e: Throwable) {
        val stackTraceInfo = getStackInfo(e)
        saveThrowableMessage(stackTraceInfo)

        object : Thread() {
            override fun run() {
                Looper.prepare()
                Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
                Looper.loop()
            }
        }.start()
    }

    private fun getStackInfo(e: Throwable): String {
        var pw: PrintWriter? = null
        var writer: Writer = StringWriter()
        try {
            pw = PrintWriter(writer)
            e.printStackTrace(pw)
        } catch (e: Exception) {
            return ""
        } finally {
            pw?.close()
        }
        return writer.toString()
    }

    private fun saveThrowableMessage(errorMessage: String) {
        if (TextUtils.isEmpty(errorMessage)) {
            return;
        }
        val file = File(logFilePath)
        if (!file.exists()) {
            val mkdirs = file.mkdirs()
            if (mkdirs) {
                writeStringToFile(errorMessage, file)
            }
        } else {
            writeStringToFile(errorMessage, file)
        }
    }

    private fun writeStringToFile(errorMessage: String, file: File) {
        var fos: FileOutputStream? = null
        try {
            val content: String = errorMessage + "[" + Utils.getCurrentDateTime() + "]\r\n"
            val bais = ByteArrayInputStream(content.toByteArray(Charsets.UTF_8))
            val crashLog = createCrashLogFile(file)
            fos = FileOutputStream(crashLog, true)
            var len: Int
            val bytes = ByteArray(1024)
            // while ((bais.read(bytes).let{ len = it; it != -1 })) {
            while ((bais.read(bytes).also{ len = it }) != -1) {
                fos.write(bytes, 0, len)
            }
            fos.flush()
            Log.e(TAG, "寫入本地文件成功:" + file.absolutePath)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            fos?.close()
        }
    }

    private fun getAllCrashFiles(): List<String> {
        val dir = File(logFilePath)
        val files = dir.listFiles()
        val fileNames = ArrayList<String>()
        for (i: Int in files.indices) {
            if (files[i].isFile) {
                fileNames.add(files[i].name)
            }
        }
        return fileNames
    }

    private fun createCrashLogFile(file: File): File {
        val sdf = SimpleDateFormat("yyyyMMdd", Locale.CHINA)
        val currentDate = sdf.format(Date())
        val crashLog = File(file, "$currentDate.txt")
        if (!crashLog.exists()) {
            crashLog.createNewFile()
            val crashLogNames = getAllCrashFiles()
            if (crashLogNames.size > 10) {
                val currentTimeMilSeconds = Date().time
                val earliestDate = sdf.format(currentTimeMilSeconds - 24 * 60 * 60 * 10 * 1000)
                deleteFile("$earliestDate.txt")
            }
        }
        return crashLog
    }

    private fun deleteFile(fileName: String) {
        val file = File(logFilePath + File.separator + fileName)
        if (file.exists()) {
            file.delete()
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章