Android自帶的日誌類不支持顯示文件名和行號,調試時很不方便。而第三方日誌庫每每又過重。因此本身對Android自帶的日誌類作了一個簡單的封裝,主要是調試時使用,不考慮日誌丟失和性能問題。日誌的輸出以下:android
08-12 13:26:25.557 31285 31285 D com.tq.test: [TestFragment.kt:85 com.tq.test.fragment.TestFragment$subscribeUi$5.onChanged] foo bar
用法以下:app
// 在Activity或Fragment中 val someValue = "abc"; getLogger().debug(someValue) getLogger().debug(someValue, x, y, z) getLogger().error(ex) // CrashHandler package com.tq.test import android.os.Process import com.tq.test.utility.Logger class DefaultExceptionHandler( private val packageName: String, private val next: Thread.UncaughtExceptionHandler? = null ): Thread.UncaughtExceptionHandler { override fun uncaughtException(thread: Thread, error: Throwable) { val logger = Logger.getLogger(packageName) logger.error(error, "uncaught exception", thread) next?.uncaughtException(thread, error) Process.killProcess(Process.myPid()) } } Thread.setDefaultUncaughtExceptionHandler(DefaultExceptionHandler( getPackageName(), Thread.getDefaultUncaughtExceptionHandler() ))
源代碼以下:ide
package com.tq.utility import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import android.content.Context import android.util.Log class Logger private constructor(val defaultTag: String = "") { fun debug(vararg values: Any?) = Log.d(defaultTag, makeMessage(values)) fun info(vararg values: Any?) = Log.i(defaultTag, makeMessage(values)) fun warn(vararg values: Any?) = Log.w(defaultTag, makeMessage(values)) fun error(error: Throwable, vararg values: Any?) = Log.e(defaultTag, makeMessage(values), error) private fun makeMessage(values: Array<out Any?>): String { // TOOD handle native method var fileName = "unknown" var lineNumber = -1 var className = "unknown" var methodName ="unknown" val throwable = Throwable() val stacks = throwable.getStackTrace() val depth = 2 if (stacks.size > depth) { val stack = stacks[depth] fileName = stack.getFileName() lineNumber = stack.getLineNumber() className = stack.getClassName() methodName = stack.getMethodName() } val valueString = values.map{ it?.toString() ?: "null" }.joinToString() return "[$fileName:$lineNumber $className.$methodName] $valueString" } companion object { fun getLogger(tag: String): Logger { return Logger(tag) } fun getLogger(context: Context) = getLogger(context.getPackageName()) } } fun AppCompatActivity.getLogger() = Logger.Companion.getLogger(this) fun Fragment.getLogger() = Logger.Companion.getLogger(activity!!)