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!!)