在android上使用全局异常处理

Using Global Exception Handling on android

是否有代码示例,或关于如何使用Thread.setDefaultUncaughtExceptionHandler方法的教程?基本上,我试图在应用程序中显示一个自定义警报对话框,每当抛出异常时。可以这样做吗?我知道在屏幕上显示一些东西有点困难,如果在UI线程中抛出异常,但我不知道有什么解决方法。


对于带着解决方案来到此页的人的基本示例:)

1
2
3
4
5
6
7
8
public class ChildActivity extends BaseActivity {
    @SuppressWarnings("unused")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int a=1/0;
    }
}

处理错误的类:

1
2
3
4
5
6
7
8
9
10
11
12
public class BaseActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                Log.e("Alert","Lets See if it Works !!!");
            }
        });
    }
}


下面是Mohit Sharma给出的答案的一个变体,有以下改进:

    百万千克1在错误处理后不会导致应用程序/服务冻结百万千克1百万千克1让android在你自己的操作之后进行正常的错误处理百万千克1

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class BaseActivity extends Activity {
    @Override
    public void onCreate() {
        super.onCreate();

        final Thread.UncaughtExceptionHandler oldHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(
                    Thread paramThread,
                    Throwable paramThrowable
                ) {
                    //Do your own error handling here

                    if (oldHandler != null)
                        oldHandler.uncaughtException(
                            paramThread,
                            paramThrowable
                        ); //Delegates to Android's error handling
                    else
                        System.exit(2); //Prevents the service/app from freezing
                }
            });
    }
}


请记住,在设置处理程序之前,会检查The RuntimePermission("setDefaultUncaughtExceptionHandler"),并确保通过抛出未捕获的异常(因为事情可能处于不确定状态),使进程在之后停止。

不要显示任何内容,实际上UI线程可能是崩溃的线程,请编写日志和/或将详细信息发送到服务器。你可能想看看这个问题及其答案。


我只是想指出我目前的经验。我正在使用https://stackoverflow.com/a/26560727/2737240建议的解决方案将异常刷新到日志文件中,然后再将控制权授予默认的异常处理程序。

但是,我的结构如下:

1
2
3
4
5
          BaseActivity
               |
    _______________________
    |          |          |
Activity A Activity B Activity C

1
2
3
4
5
6
7
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                          
        @Override                                                                                                                                                                                                                                                                                                                                                                                                              
        public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                            
            handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
        }                                                                                                                                                                                                                                                                                                                                                                                                                      
 });

其中handleUncaughtException(thread, e, defaultEH);写入日志并将调用移交给原始的未捕获异常处理程序。

所以使用这个代码所发生的事情是:

    百万千克1活动A已实例化百万千克1百万千克1新的默认异常处理程序(DEH)现在是我的日志处理程序+旧的DEH百万千克1百万千克1活动B已实例化百万千克1百万千克1新DEH现在是我的日志处理程序+旧DEH(日志处理程序+原始DEH)百万千克1百万千克1活动C已实例化百万千克1百万千克1新DEH现在是我的日志处理程序+旧DEH(日志处理程序+日志处理程序+原始DEH)百万千克1

因此,这是一个无限增长的链条,导致了两个问题:

百万千克1指定的自定义代码(在我的例子中是写入日志文件)将被多次调用,这不是所需的操作。百万千克1百万千克1defaulteh的引用甚至在活动完成后仍保留在堆中,因为引用链使用了它,所以可能发生的最糟糕的事情是内存不足异常。百万千克1

因此,我又增加了一件事,最终使这项工作顺利进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static boolean customExceptionHandlerAttached = false;                                                                                                                                                                                                                                                                                                                                                                      

@Override                                                                                                                                                                                                                                                                                                                                                                                                                          
protected void onCreate(@Nullable Bundle savedInstanceState) {                                                                                                                                                                                                                                                                                                                                                                      
    super.onCreate(savedInstanceState);                                                                                                                                                                                                                                                                                                                                                                                            

    if(!customExceptionHandlerAttached) {                                                                                                                                                                                                                                                                                                                                                                                            
        final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();                                                                                                                                                                                                                                                                                                                              
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {                                                                                                                                                                                                                                                                                                                                          
            @Override                                                                                                                                                                                                                                                                                                                                                                                                              
            public void uncaughtException(Thread thread, Throwable e) {                                                                                                                                                                                                                                                                                                                                                            
                 handleUncaughtException(thread, e, defaultEH);                                                                                                                                                                                                                                                                                                                                                                      
            }                                                                                                                                                                                                                                                                                                                                                                                                                      
        });                                                                                                                                                                                                                                                                                                                                                                                                                        
        customExceptionHandlerAttached = true;                                                                                                                                                                                                                                                                                                                                                                                      
    }                                                                                                                                                                                                                                                                                                                                                                                                                              
}

使用此解决方案,我们可以确保:

    百万千克1为所需操作添加自定义异常处理程序百万千克1百万千克1确保此操作仅触发一次百万千克1百万千克1允许垃圾收集器通过调用finish()完全处理我们的活动百万千克1


如果你想使用这个库

https://github.com/selimtoksal/android-catch-global-exception-library

创建TransferObject并非所有活动都只用于基本活动