Android 崩溃后不闪退的实现

1. 整体流程

为了实现 Android 应用崩溃后不闪退的效果,我们可以通过以下流程来完成:

journey
    title Android 崩溃后不闪退的实现流程
    section 捕获崩溃信息
    section 处理崩溃信息
    section 重启应用

2. 捕获崩溃信息

在应用崩溃时,我们需要捕获崩溃的信息,可以通过设置一个全局的异常处理器来实现。

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static CrashHandler instance;
    private Context context;
    private Thread.UncaughtExceptionHandler defaultExceptionHandler;

    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        if (instance == null) {
            instance = new CrashHandler();
        }
        return instance;
    }

    public void init(Context context) {
        this.context = context;
        // 获取系统默认的异常处理器
        defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置该异常处理器为全局异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
        // 处理崩溃信息
        handleCrash(throwable);
        if (defaultExceptionHandler != null) {
            // 如果系统默认的异常处理器存在,则交给它处理
            defaultExceptionHandler.uncaughtException(thread, throwable);
        }
    }

    private void handleCrash(Throwable throwable) {
        // TODO: 处理崩溃信息,比如保存日志到文件
    }
}

在自定义的 CrashHandler 类中,我们实现了 Thread.UncaughtExceptionHandler 接口,并在 uncaughtException 方法中处理崩溃信息。在 handleCrash 方法中,我们可以将崩溃信息保存到文件,方便后续分析和调试。

3. 处理崩溃信息

在捕获到崩溃信息后,我们需要对其进行处理,比如展示一个友好的提示界面或者上传崩溃日志到服务器。

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    // ...

    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
        // 处理崩溃信息
        handleCrash(throwable);
        if (defaultExceptionHandler != null) {
            // 如果系统默认的异常处理器存在,则交给它处理
            defaultExceptionHandler.uncaughtException(thread, throwable);
        } else {
            // 没有默认的异常处理器,自己处理崩溃信息
            showCrashDialog();
            // 或者上传崩溃日志到服务器
            // uploadCrashLog();
        }
    }

    private void showCrashDialog() {
        // TODO: 展示一个友好的崩溃提示对话框
    }

    private void uploadCrashLog() {
        // TODO: 上传崩溃日志到服务器
    }
}

在上述代码中,我们在 uncaughtException 方法中判断是否存在默认的异常处理器,如果存在则交给它处理,否则我们可以展示一个友好的崩溃提示对话框或者将崩溃日志上传到服务器。

4. 重启应用

如果用户选择重启应用,我们需要在崩溃提示对话框中添加相应的重启逻辑。

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    // ...

    private void showCrashDialog() {
        // 创建一个对话框用于展示崩溃提示信息
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("应用崩溃");
        builder.setMessage("应用崩溃了,是否重启应用?");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 重启应用
                restartApplication();
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 关闭应用
                exitApplication();
            }
        });
        builder.setCancelable(false);
        builder.show();
    }

    private void restartApplication() {
        // 通过隐式 Intent 重启应用
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.get