android——异常捕获崩溃后重新启动App

简介

我们在开发或者测试阶段不能做到100%的问题解决,因为 app 上线之后会有你想不到的各种各样的使用的场景,而发生问题时用户只能描述一下怎么怎么怎么就出现了问题。也许反馈到开发这边可以100%复现那就可以得到解决,但是也有可能在本地复现不了(PS:我没问题啊),只有在用户的手机上可以出现,这可能和用户使用的场景(温度太高导致CPU限速,温度太低等),手机的内存,CPU,老年机等等都有关系。
一旦发生异常就崩溃了,带给用户的体验非常的不好,所以我们可以通过重新启动App方式来提升用户体验。
  1. 封装一个异常捕获的类

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

最后,异常每个人都会遇到,希望这篇文章能帮助到大家。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wy313622821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值