android 全局异常捕获,防止崩溃发生

Posted mjsoftwareking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 全局异常捕获,防止崩溃发生相关的知识,希望对你有一定的参考价值。

主类

/**
 * 用途:全局异常拦截
 * <p>
 * 作者:mjSoftKing
 */
public class NeverCrash 

    private final static String TAG = NeverCrash.class.getSimpleName();
    private final static NeverCrash INSTANCE = new NeverCrash();

    private boolean debugMode;
    private MainCrashHandler mainCrashHandler;
    private UncaughtCrashHandler uncaughtCrashHandler;

    private NeverCrash() 
    

    public static NeverCrash getInstance() 
        return INSTANCE;
    

    private synchronized MainCrashHandler getMainCrashHandler() 
        if (null == mainCrashHandler) 
            mainCrashHandler = (t, e) -> 
            ;
        
        return mainCrashHandler;
    

    /**
     * 主线程发生异常时的回调,可用于打印日志文件
     * <p>
     * 注意跨线程操作的可能
     */
    public NeverCrash setMainCrashHandler(MainCrashHandler mainCrashHandler) 
        this.mainCrashHandler = mainCrashHandler;
        return this;
    

    private synchronized UncaughtCrashHandler getUncaughtCrashHandler() 
        if (null == uncaughtCrashHandler) 
            uncaughtCrashHandler = (t, e) -> 
            ;
        
        return uncaughtCrashHandler;
    

    /**
     * 子线程发生异常时的回调,可用于打印日志文件
     * <p>
     * 注意跨线程操作的可能
     */
    public NeverCrash setUncaughtCrashHandler(UncaughtCrashHandler uncaughtCrashHandler) 
        this.uncaughtCrashHandler = uncaughtCrashHandler;
        return this;
    

    private boolean isDebugMode() 
        return debugMode;
    

    /**
     * debug模式,会打印log日志,且toast提醒发生异常,反之则都没有
     */
    public NeverCrash setDebugMode(boolean debugMode) 
        this.debugMode = debugMode;
        return this;
    

    /**
     * 完成监听异常的注册
     * @param application application
     */
    public void register(Application application) 
        //主线程异常拦截
        new Handler(Looper.getMainLooper()).post(() -> 
            while (true) 
                try 
                    Looper.loop();
                 catch (Throwable e) 
                    if (isDebugMode()) 
                        Log.e(TAG, "未捕获的主线程异常行为", e);
                        new Handler(Looper.getMainLooper()).post(() ->
                                Toast.makeText(application, "主线程发生异常,请查看控制台日志!\\n此提醒和控制台打印仅在debug版本下有效!", Toast.LENGTH_LONG).show());
                    
                    getMainCrashHandler().mainException(Looper.getMainLooper().getThread(), e);
                
            
        );

        //子线程异常拦截
        Thread.setDefaultUncaughtExceptionHandler((t, e) -> 
            if (isDebugMode()) 
                Log.e(TAG, "未捕获的子线程异常行为", e);
                new Handler(Looper.getMainLooper()).post(() ->
                        Toast.makeText(application, "子线程发生异常,请查看控制台日志!\\n此提醒和控制台打印仅在debug版本下有效!", Toast.LENGTH_LONG).show());
            
            getUncaughtCrashHandler().uncaughtException(t, e);
        );
    

    public interface MainCrashHandler 
        void mainException(Thread t, Throwable e);
    

    public interface UncaughtCrashHandler 
        void uncaughtException(Thread t, Throwable e);
    

application下使用

/**
 * 用途:
 * <p>
 * 作者:mjSoftKing
 * 时间:2021/04/26
 */
public class App extends Application 

    private final static String TAG = App.class.getSimpleName();

    @Override
    public void onCreate() 
        super.onCreate();
        NeverCrash.getInstance()
                .setDebugMode(BuildConfig.DEBUG)
                .setMainCrashHandler((t, e) -> 
                    //todo 跨线程操作时注意线程调度回主线程操作
                    Log.e(TAG, "主线程异常");//此处log只是展示,当debug为true时,主类内部log会打印异常信息
                    //todo 此处做你的日志记录即可
                )
                .setUncaughtCrashHandler((t, e) -> 
                    //todo 跨线程操作时注意线程调度回主线程操作
                    Log.e(TAG, "子线程异常");//此处log只是展示,当debug为true时,主类内部log会打印异常信息
                    //todo 此处做你的日志记录即可
                )
                .register(this);

    

最后别忘了注册application类

<manifest ...>

    <application
        android:name=".App"
        ...>
        ...
    </application>

</manifest>

 

以上是关于android 全局异常捕获,防止崩溃发生的主要内容,如果未能解决你的问题,请参考以下文章

Android 捕获主线程异常崩溃

Android 捕获全局异常CrashHandler,防止异常闪退,记录异常日志

全局捕获所有可能的android异常并重新加载应用程序

如何防止程序崩溃

Kotlin 协程协程异常处理 ④ ( Android 协程中出现异常导致应用崩溃 | Android 协程中使用协程异常处理器捕获异常 | Android 全局异常处理器 )

Kotlin 协程协程异常处理 ④ ( Android 协程中出现异常导致应用崩溃 | Android 协程中使用协程异常处理器捕获异常 | Android 全局异常处理器 )