简介
我们在开发或者测试阶段不能做到100%的问题解决,因为 app 上线之后会有你想不到的各种各样的使用的场景,而发生问题时用户只能描述一下怎么怎么怎么就出现了问题。也许反馈到开发这边可以100%复现那就可以得到解决,但是也有可能在本地复现不了(PS:我没问题啊),只有在用户的手机上可以出现,这可能和用户使用的场景(温度太高导致CPU限速,温度太低等),手机的内存,CPU,老年机等等都有关系。
一旦发生异常就崩溃了,带给用户的体验非常的不好,所以我们可以通过重新启动App方式来提升用户体验。
封装一个异常捕获的类
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Looper
import android.util.Log
import android.widget.Toast
/**
* @author MrLiu
* @date 2020/5/13
* desc 捕获异常
*/
class CrashHandler(myApplication: MyApplication) : Thread.UncaughtExceptionHandler {
private val mDefaultHandler: Thread.UncaughtExceptionHandler? = Thread.getDefaultUncaughtExceptionHandler()
var application: MyApplication
init {
// // 获取系统默认的UncaughtException处理器
application = myApplication
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
override fun uncaughtException(thread: Thread, ex: Throwable) {
if (!handlerException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex)
} else {
try {
Thread.sleep(1500)
} catch (e: InterruptedException) {
Log.e("CatchExcep", "error ;", e)
}
// 重启app
val intent = Intent(application.applicationContext, MainActivity::class.java)
//PendingIntent restartIntent = PendingIntent.getActivity(application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
val restartIntent = PendingIntent.getActivity(
MyApplication.context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
// 退出程序
val mgr = application.getSystemService(Context.ALARM_SERVICE) as AlarmManager
// 1秒后重启
mgr[AlarmManager.RTC, System.currentTimeMillis() + 1000] = restartIntent
//关闭已打开的Activity后,杀死应用进程(其实有点画蛇添足,因为杀死应用进城时会自动关闭所有的Activity等 ~)
application.finishAllActivity()
}
}
/**
* 获取具体异常,此处可做崩溃前的处理
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private fun handlerException(ex: Throwable?): Boolean {
if (ex == null) {
return false
}
// 发个友好的提示,弹个土司 - 此处只是为了效果,可进行注释或替换为自己的逻辑代码
object : Thread() {
override fun run() {
Looper.prepare()
Toast.makeText(application.applicationContext, "检测到程序异常,即将退出", Toast.LENGTH_SHORT)
.show()
// Log.e("CrashHandler","CrashHandler=>+${ex.message}")
Looper.loop()
}
}.start()
return true
}
}
2、application中初始化
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.Context
import android.os.Process
/**
* @author MrLiu
* @date 2020/5/13
* desc
*/
class MyApplication : Application() {
var activityList: MutableList<Activity> = ArrayList()
override fun onCreate() {
super.onCreate()
context = applicationContext
// 设置该CrashHandler为程序的默认处理器
val unCeHandler = CrashHandler(this)
Thread.setDefaultUncaughtExceptionHandler(unCeHandler)
}
/**
* @param activity activity关闭时,删除Activity列表中的Activity对象
*/
fun removeActivity(activity: Activity) {
activityList.remove(activity)
}
/**
* @param activity 向列表中添加Activity对象
*/
fun addActivity(activity: Activity) {
activityList.add(activity)
}
/**
* 关闭Activity列表中的 所有Activity
*/
fun finishAllActivity() {
for (activity in activityList) {
activity?.finish()
}
// 杀死应用进程
Process.killProcess(Process.myPid())
}
companion object {
/**
* context
*/
@SuppressLint("StaticFieldLeak")
var context: Context? = null
private set
}
}
3、异常产生
var aar: ArrayList<String>? = null
// 数组越界异常
fun arrCrash(view: View) {
val aar = ArrayList<String>()
aar[1] = "0"
}
// 空指针异常
fun nullCrash(view: View) {
aar!!.size
}
重启app这是一种解决方式,还有另外一种方式可以集成三方平台用于捕获异常,例如:Bugly
最后,异常每个人都会遇到,希望这篇文章能帮助到大家。