You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止Android应用停止后自动重启?未捕获异常处理求助

我帮你梳理下解决这两个问题的具体方案,结合你已经在做的Sentry日志上报,一步步来:

一、处理未捕获异常并直接关闭应用,避免系统弹窗

你之前继承Activity重写uncaughtException()的方式可能不够彻底,因为Android系统默认的Thread.UncaughtExceptionHandler会接管全局未捕获异常,进而触发重启弹窗。正确的做法是替换系统默认的异常处理器,在捕获异常后完成日志上报,再彻底终止应用:

1. 自定义全局异常处理器

创建一个实现Thread.UncaughtExceptionHandler的类,接管所有未捕获异常:

public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler {
    private final Thread.UncaughtExceptionHandler defaultSystemHandler;
    private final Application application;

    public GlobalExceptionHandler(Application app) {
        // 保存系统默认的异常处理器(可选,如果你想在某些场景 fallback 回去)
        defaultSystemHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = app;
    }

    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
        // 1. 上报异常到 Sentry
        Sentry.captureException(throwable);

        // 2. (可选)短暂延迟,确保异步上报的日志能发送完成
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 3. 关闭所有已启动的 Activity
        AppManager.getInstance().finishAllActivities();

        // 4. 标记应用是异常退出(用于后续阻止重启)
        markCrashState();

        // 5. 彻底终止进程,不要调用系统默认处理器,否则仍会弹窗
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
    }

    private void markCrashState() {
        // 用 SharedPreferences 记录崩溃状态
        SharedPreferences sp = application.getSharedPreferences("app_internal", Context.MODE_PRIVATE);
        sp.edit().putBoolean("is_crashed", true).apply();
    }
}

2. 实现Activity管理类(用于关闭所有页面)

需要一个全局的Activity栈管理类,方便在崩溃时关闭所有页面:

public class AppManager {
    private static AppManager instance;
    private final List<Activity> activityList = new ArrayList<>();

    private AppManager() {}

    public static AppManager getInstance() {
        if (instance == null) {
            synchronized (AppManager.class) {
                if (instance == null) {
                    instance = new AppManager();
                }
            }
        }
        return instance;
    }

    // 添加Activity到栈
    public void addActivity(Activity activity) {
        activityList.add(activity);
    }

    // 移除Activity
    public void removeActivity(Activity activity) {
        activityList.remove(activity);
    }

    // 关闭所有Activity
    public void finishAllActivities() {
        for (Activity activity : activityList) {
            if (activity != null && !activity.isFinishing()) {
                activity.finish();
            }
        }
        activityList.clear();
    }
}

3. 在Application中注册异常处理器和Activity管理

在你的自定义Application类中完成初始化:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // 1. 注册全局异常处理器
        Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler(this));

        // 2. 注册Activity生命周期回调,自动管理Activity栈
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                AppManager.getInstance().addActivity(activity);
            }

            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {
                AppManager.getInstance().removeActivity(activity);
            }

            // 其他生命周期方法可以留空
            @Override public void onActivityStarted(@NonNull Activity activity) {}
            @Override public void onActivityResumed(@NonNull Activity activity) {}
            @Override public void onActivityPaused(@NonNull Activity activity) {}
            @Override public void onActivityStopped(@NonNull Activity activity) {}
            @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}
        });
    }
}
二、阻止应用异常退出后自动重启

有些Android厂商(如OPPO、vivo)或系统服务可能会在应用崩溃后自动重启,我们可以通过启动状态校验来阻止这种行为:

1. 在Application启动时判断崩溃状态

修改MyApplication的onCreate()方法,加入崩溃状态校验:

@Override
public void onCreate() {
    super.onCreate();

    // 先检查是否是崩溃后重启
    SharedPreferences sp = getSharedPreferences("app_internal", Context.MODE_PRIVATE);
    boolean wasCrashed = sp.getBoolean("is_crashed", false);
    if (wasCrashed) {
        // 重置崩溃标记并直接退出
        sp.edit().putBoolean("is_crashed", false).apply();
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
        return;
    }

    // 下面是原来的初始化代码
    Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler(this));
    registerActivityLifecycleCallbacks(...);
}

关键注意事项

  • 不要调用系统默认的defaultSystemHandler.uncaughtException(),否则系统仍会弹出重启提示。
  • 延迟上报的时间可以根据实际情况调整,确保Sentry日志能成功发送(如果Sentry是同步上报则不需要延迟)。
  • 对于某些厂商的后台保活机制,可能需要在Manifest中关闭不必要的权限或组件,但上述方案已经能覆盖大多数场景。

内容的提问来源于stack exchange,提问作者Clamorious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:20:33