The scene that
Most of the projects that are currently online have a mechanism to catch crashes, some of which may be self-written, some of which may be using a third party, such as Bugly.
However, no matter what framework is used, it basically revolves around UncaughtExceptionHandler, which means that an exception can only be reported if the application crashes.
Huh? Why does the app crash to report information?
That’s because most frameworks use this method for exception catching and reporting:
Thread.setDefaultUncaughtExceptionHandler(object : Thread.UncaughtExceptionHandler { override fun uncaughtException(t: Thread, e: Throwable) {// Record and report exceptions. . // Invoke system default crash handling. . }})Copy the code
DefaultUncaughtExceptionHandler there is only one, it is not the responsibility chain form. As a result, if you use a third party framework, all exception handling is left to it, and it is difficult to change the logic in it unless it provides the source code or provides the corresponding callback.
So, I was wondering if there was a way to use the exception capture mechanism, but ultimately handle the exception information ourselves, rather than simply calling the system’s default crash handling. For example, we wanted to add automatic restart.
You can follow me to explore!
Please fasten your seat belts. GO! GO! GO!
Nothing ventured, nothing gained. First, we need to understand the basic use of UncaughtExceptionHandler.
UncaughtExceptionHandler Usage instructions
The general idea is as follows:
- Storage system default exception handling
- implementation
UncaughtExceptionHandler
interface - in
uncaughtException
Do the exception handling logic, and then invoke the system default exception handling - call
Thread.setDefaultUncaughtExceptionHandler()
set
The specific code is as follows:
MyUncaughtExceptionHandler. Kt:
object MyUncaughtExceptionHandler : Thread. UncaughtExceptionHandler {/ / get the default system the exception handling mechanism of private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler() override fun uncaughtException(t: Thread, e: Log.e("uncaughtException TAG", E.m essage. ToString ()) / / / / to the system default processing / / defaultUncaughtExceptionHandler uncaughtException (t, e)}}Copy the code
BaseApplication. Kt:
class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler)
}
}
Copy the code
From this, we can catch the App’s crash exception.
Now, we can consider another question.
We know that Bugly also has this code in it, how can we do that and get our hands on the system default crash handling to change it?
em…
Intercept Bugly’s crash handling
First of all, we have to think, how to get the system default defaultUncaughtExceptionHandler Bugly?
. There is no doubt that it is through the Thread getDefaultUncaughtExceptionHandler () of this method to obtain, and stored, as we wrote the code below.
private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler =
Thread.getDefaultUncaughtExceptionHandler()
Copy the code
So, so, we’re Bugly initialization code before they get the system default defaultUncaughtExceptionHandler stored, and then put the custom MyUncaughtExceptionHandler set as default, then, Bugly get defaultUncaughtExceptionHandler not is our custom that?
Then, after Bugly handles the exception, we call the default crash handler, which is our crash handler, and we can do whatever we want!
The code is as follows:
class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler)
CrashReport.initCrashReport(getApplicationContext(), "123456", false)
}
}
Copy the code
MyUncaughtExceptionHandler code I stick down:
object MyUncaughtExceptionHandler : Thread. UncaughtExceptionHandler {/ / get the default system the exception handling mechanism of private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler() override fun uncaughtException(t: Thread, e: Log.e("uncaughtException TAG", E.m essage. ToString ()) / / / / to the system default processing / / defaultUncaughtExceptionHandler uncaughtException (t, e)}}Copy the code
Write an exception and click View to throw an exception:
tv_login.setOnClickListener {
"a".toInt()
}
Copy the code
Run:
Exception successfully caught:
E/uncaughtException TAG: For input string: "a"
Copy the code
Bugly also reported an anomaly:
Thus, we can add your own exception handling functions in MyUncaughtExceptionHandler, restart the App, for example, or to collect data, etc.
Of course, this logic is not limited to Bugly, but can be applied to any framework that handles exceptions around UncaughtExceptionHandler.
Guess you like
- Make an App that never crashes
- Custom Gradle Plugin+ bytecode staking
- From handwritten ButterKnife to mastering annotations, AnnotationProcessor
- Here, I want you to write a performance check
It’s not easy, and your likes are my biggest support.