Causes and Solutions of Android app Meeting crash

  • 2021-12-11 09:07:02
  • OfStack

In the commonInit () method of android main entry, there is such a sentence.


Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

Without this sentence, app would not be crash. If you don't believe me, look inside,


public KillApplicationHandler(LoggingHandler loggingHandler) {
 @Override
 public void uncaughtException(Thread t, Throwable e) {
 // Exception caught 
   try {
     ......
     // Print crash Log, show crash pop-up window, etc. 
     // Bring up crash dialog, wait for it to be dismissed
     ActivityManager.getService().handleApplicationCrash(
       mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
      } catch (Throwable t2) {
        .... 
      } finally {
        // Try everything to make sure this process goes away.
        Process.killProcess(Process.myPid());// Kill process 
        System.exit(10);
      }
    }
  } 

When the exception KillApplicationHandler catches the exception, after 1 series of processing (mainly printing crash log, notifying AMS to show crash pop-up window, etc.), it will eventually kill the process, so that your app will crash.

Now that everything has crashed, is it really feasible to customize exception traps to mask crash?

Some people will definitely say, customize an exception tracker to overwrite the KillApplicationHandler of the system, and then after catching the exception, app will not crash without killing the process, just like the following.


class MainApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    Thread.setDefaultUncaughtExceptionHandler { _, e ->
      // If an exception is caught, only the log will be printed, and the process will not be killed 
      Log.e("MainApplication", "${Thread.currentThread().name}  Exception caught: ${e.message}")
    }
  }
}

In fact, this is just the thinking of Lao Wang next door. Although it does protect the crash of sub-threads, app still cannot run normally when the main thread is abnormal. This is because when UncaughtExceptionHandler catches a thread throwing an exception, the thread cannot survive after executing the processing in uncaughtException (). If the thread that throws the exception is the main thread, it means that the main thread will die. At this time, even if you don't kill the process, it doesn't make any sense for the process to live, and app will still stop running.

The android exception capture mechanism is combed under 1, and familiar students can skip it and go directly to the next section.

Thread. setCaughtExceptionPreHandler () overrides all threads and is called before a callback to DefaultExceptionHandler; Thread. setCaughtExceptionHandler () also covers all threads, and can be called repeatedly in the application layer, and after each call, it will overwrite the DefaultUncaughtExceptionHandler; set once; Thread. currentThread. setUncaughtExceptionHandler () can only override exceptions for the current thread. If a custom UncaughtExceptionHandler exists for a thread, the global DefaultUncaughtHandler is ignored on callback.

Now that we have said this, please take never crash.

If you want to avoid crash, you can only ask the thread not to throw exception, but there is no other way. If we can protect all the operations of a thread with try-catch, in theory, we can achieve app never crash. Because android is based on Handler event-driven mechanism, when app is started, an infinite loop operation can be submitted to MessageQueue in the main thread, poll events are continuously removed in this infinite loop, and this infinite loop is carried out try-catch, so that all exceptions in the main thread will be stopped by catch, and crash will never happen again.


private fun openCrashProtected() {
    Log.d(tag, "openCrashProtected")
    Handler(Looper.getMainLooper()).post {
      while (true) {
        try {
          Looper.loop()
          Log.d(tag, "main looper execute loop")
        } catch (e: Throwable) {
          // Exceptions in all main threads will be catch Live, so that it won't happen crash
          Log.e(tag, "catch exception: " + e.message)
        }
      }
    }
  }

Some people may have to say that you are so catch live in the main thread of the exception, the page may be messed up wow. Having said that, you can do business protection in catch. For example, what I do here is to close the top activity. Solve ActivityLifeCycle, maintain an Activity stack,


private fun registerLifeCycle() {
    registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
      override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        ActivityStack.Instance().push(activity)
      }

      override fun onActivityResumed(activity: Activity) {
      }

      override fun onActivityStarted(activity: Activity) {
      }

      override fun onActivityPaused(activity: Activity) {

      }

      override fun onActivityDestroyed(activity: Activity) {
        ActivityStack.Instance().pop(activity)
      }

      override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {

      }

      override fun onActivityStopped(activity: Activity) {
      }
    })
  }

Then when catch is abnormal,


// Exception occurred in the main thread, closing the top of the stack activity
ActivityStack.Instance().curr()?.finish()

github code

Finally, please accept the github warehouse code.

The above is the reason why Android app will meet crash and the detailed content of the solution. For more information about Android app crash, please pay attention to other related articles on this site!


Related articles: