How to catch the exception of app crash and restart the application [can be used to keep the app alive]

Preface

In app development, it is inevitable that some unexpected problems will cause the app to crash. If the application cannot automatically restart, it will greatly affect the user experience. For example, the service of chat software that accepts messages in the background needs to always exist. If it cannot be restored in time after a crash, many messages will be missed. Another example is that ordinary weather applications need to obtain the weather regularly. If it cannot be restored in time after a crash, the user's understanding of the weather will lag, which may affect the user's travel.

In response to the above problems, improving the stability of the app is the most important, but we still need to save a hand to ensure that we can protect ourselves after the first layer of defense is breached.



Relevant knowledge supplement

There are two types of exceptions in Java: Checked exceptions and Unchecked exceptions. The former must use throws or try catch for exception handling, such as Thread.sleep()file reading and writing; the latter does not need to be specified or captured, such as array out-of-bounds exceptions and null pointer exceptions.

Java's default handling of undetected exceptions is to write the stack trace information to the console (or log it to the error log file) and then exit the program.

When a thread is about to terminate due to an uncaught exception, the Java Virtual Machine will Thread.getUncaughtExceptionHandler()query the thread using the method UncaughtExceptionHandlerand will call the handler's uncaughtExceptionmethod, passing the thread and exception as arguments.

If the thread has not explicitly set it UncaughtExceptionHandler, its ThreadGroupobject will act as it UncaughtExceptionHandler. If ThreadGroupthe object has no special requirements for handling exceptions, it can forward the call to the default uncaught exception handler.



accomplish

Based on the above principles, we can build a class, inherit the Java UncaughtExceptionHandlerinterface, and override uncaughtExceptionthe method to handle the crash problem and restart the application .

public class UnCeHandler implements Thread.UncaughtExceptionHandler {
    
    
    private final Thread.UncaughtExceptionHandler mDefaultHandler;
    Application application;
    
    public UnCeHandler(Application application) {
    
    
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = application;
    }
    
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
    
    
        //....
    }
}

In uncaughtException(Thread thread, Throwable ex), we can add custom exception handling

@Override
public void uncaughtException(Thread thread, Throwable ex) {
    
    
    if (!handleException(ex) && mDefaultHandler != null) {
    
    
        //如果用户没有处理则让系统默认的异常处理器来处理
        mDefaultHandler.uncaughtException(thread, ex);
    } else {
    
    
        //设置定时重启
        Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
        PendingIntent restartIntent = PendingIntent.getActivity(
            application.getApplicationContext(), 
            0, 
            intent, 
            PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
        //kill应用
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

It handleException(ex)can be used to collect crash information and perform operations such as file storage or pop-up Toast.

private boolean handleException(Throwable ex) {
    
    
    if (ex == null) {
    
    
        return false;
    }
    //TODO:在此处处理捕获到的crash信息
    return true;
}

The AlarmManager in the program is a timer in Android. By passing the PendingIntent object, the specified activity, service or broadcast can be started regularly, so that the app can be restarted regularly after being killed.

Note : For the crash restart of background services, 8.0 and above need to be woken PendingIntent.getForegroundService()up. At the same time, the background service to be awakened must be started in the foreground.

PendingIntent restartIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
    restartIntent = PendingIntent.getForegroundService(
            application.getApplicationContext(), 0, intent, 0);
} else {
    
    
    restartIntent = PendingIntent.getService(
            application.getApplicationContext(), 0, intent, 0);
}
AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);

Finally, by setting a custom exception capture processor in the application, you can capture the exceptions of all threads globally.

public class MyApplication extends Application {
    
    

    @Override
    public void onCreate() {
    
    
        super.onCreate();
        //程序崩溃时触发线程  以下用来捕获程序崩溃异常
        Thread.setDefaultUncaughtExceptionHandler(new UnCeHandler(this));
    }
}


Summarize

The idea of ​​restarting an application after an abnormal crash is to Thread.UncaughtExceptionHandlercapture the exception of the app crash and then AlarmManagerreopen the application or background service by sending a scheduled broadcast.

Guess you like

Origin blog.csdn.net/Guan_li_peng/article/details/128972392