blob: 6c60829a77e70f7e21019853b3b09d45db876dc6 [file] [log] [blame]
package com.supwisdom.activities
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Looper
import com.supwisdom.utils.*
import com.supwisdom.view.ToastUtil
import java.io.PrintWriter
import java.io.StringWriter
import java.util.*
/**
** create by zzq on 2019/7/23
** @desc
**/
@Suppress("DEPRECATION")
class CrashHandler : Thread.UncaughtExceptionHandler {
private var context: Context? = null
private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null
private val info = HashMap<String, String>()
companion object {
@SuppressLint("StaticFieldLeak")
private var INSTANCE: CrashHandler? = null
fun getInstance(): CrashHandler {
if (INSTANCE == null) {
synchronized(CrashHandler::class) {
if (INSTANCE == null) {
INSTANCE = CrashHandler()
}
}
}
return INSTANCE!!
}
}
fun init(context: Context) {
this.context = context
// 获取系统默认的 UncaughtException 处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
// 设置该 CrashHandler 为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this)
}
override fun uncaughtException(thread: Thread, ex: Throwable) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果自定义的没有处理则让系统默认的异常处理器来处理
mDefaultHandler!!.uncaughtException(thread, ex)
} else {
AppExitUtil.exit()
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex 异常信息
* @return true 如果处理了该异常信息;否则返回false.
*/
private fun handleException(ex: Throwable?): Boolean {
ThreadPool.getShortPool().execute(Runnable {
CommonUtil.doSleep(500)
Looper.prepare()
ToastUtil.show(context!!, "很抱歉,程序运行异常")
Looper.loop()
})
if (ex == null) {
return false
}
// 收集设备参数信息
collectDeviceInfo()
// 保存日志文件
saveCrashInfo2File(ex)
return true
}
/**
* 收集设备参数信息
*/
private fun collectDeviceInfo() {
try {
val pm = context!!.packageManager// 获得包管理器
val pi = pm.getPackageInfo(
context!!.packageName,
PackageManager.GET_ACTIVITIES
)// 得到该应用的信息,即主Activity
if (pi != null) {
info["versionName"] = pi.versionName ?: "null"
info["versionCode"] = pi.versionCode.toString()
}
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
val fields = Build::class.java.declaredFields// 反射机制
for (field in fields) {
try {
field.isAccessible = true
info[field.name] = field.get("").toString()
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
}
}
private fun saveCrashInfo2File(ex: Throwable): Boolean {
val sb = StringBuffer()
sb.append("\r\n crash time :").append(DateUtil.getNowTime()).append("\r\n")
for ((key, value) in info) {
sb.append("$key=$value\r\n")
}
val writer = StringWriter()
val pw = PrintWriter(writer)
ex.printStackTrace(pw)
var cause: Throwable? = ex.cause
// 循环着把所有的异常信息写入writer中
while (cause != null) {
cause.printStackTrace(pw)
cause = cause.cause
}
pw.close()// 记得关闭
val result = writer.toString()
sb.append(result)
// 保存文件
FileUtil.writeCrashFile(sb.toString())
return true
}
}