Programing

Android에서 잡히지 않은 전역 예외 처리기를 설정하는 이상적인 방법

lottogame 2020. 9. 19. 11:55
반응형

Android에서 잡히지 않은 전역 예외 처리기를 설정하는 이상적인 방법


내 Android 애플리케이션의 모든 스레드에 대해 잡히지 않은 전역 예외 처리기를 설정하고 싶습니다. 따라서 내 Application하위 클래스 Thread.UncaughtExceptionHandler에서 포착되지 않은 예외에 대한 기본 처리기로 구현을 설정했습니다 .

Thread.setDefaultUncaughtExceptionHandler(
                new DefaultExceptionHandler(this));

내 구현에서 AlertDialog적절한 예외 메시지 를 표시하려고 합니다.

그러나 이것은 작동하지 않는 것 같습니다. 처리되지 않은 스레드에 대해 예외가 발생할 때마다 재고 OS 기본 대화 상자 ( "Sorry! -Application-has-stopped-unexpectedly dialog")가 표시됩니다.

포착되지 않은 예외에 대한 기본 처리기를 설정하는 정확하고 이상적인 방법은 무엇입니까?


그게 당신이해야 할 전부입니다. (나중에 프로세스가 중단되도록해야합니다. 상황이 불확실한 상태 일 수 있습니다.)

가장 먼저 확인해야 할 것은 Android 핸들러가 여전히 호출되고 있는지 여부입니다. 버전이 호출되고 있지만 치명적으로 실패하고 system_server가 프로세스 충돌을 볼 때 일반 대화 상자를 표시 할 수 있습니다.

처리기 상단에 몇 가지 로그 메시지를 추가하여 처리되는지 확인합니다. getDefaultUncaughtExceptionHandler에서 결과를 인쇄 한 다음 포착되지 않은 예외를 발생시켜 충돌을 유발합니다. 무슨 일이 일어나고 있는지 보려면 logcat 출력을 주시하십시오.


오래 전에 Android 충돌을 사용자 지정 처리하기위한 간단한 솔루션게시했습니다 . 약간 해키하지만 모든 Android 버전 (Lollipop 포함)에서 작동합니다.

먼저 약간의 이론. Android에서 포착되지 않은 예외 처리기를 사용할 때 발생하는 주요 문제는 기본 (일명 UI) 스레드에서 발생하는 예외와 함께 발생합니다. 그리고 여기에 그 이유가 있습니다. 앱이 시작되면 시스템이 앱 Main looper 를 준비하고 시작하는 ActivityThread.main 메서드를 호출 합니다.

public static void main(String[] args) {
    Looper.prepareMainLooper();
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

메인 루퍼는 UI 스레드에 게시 된 메시지를 처리합니다 (UI 렌더링 및 상호 작용과 관련된 모든 메시지 포함). UI 스레드에서 예외가 발생하면 예외 처리기에 의해 포착되지만 loop()메서드를 벗어 났기 때문에 UI 메시지를 처리 ​​할 사람이 남아 있지 않으므로 사용자에게 대화 나 활동을 표시 할 수 없습니다. 당신을 위해.

제안 된 솔루션은 매우 간단합니다. Looper.loop자체적으로 메소드를 실행 하고 try-catch 블록으로 둘러 쌉니다. 예외가 발견되면 원하는대로 처리하고 (예 : 사용자 지정 보고서 활동 시작) Looper.loop메서드를 다시 호출 합니다.

다음 메소드는이 기술을 보여줍니다 ( Application.onCreate리스너 에서 호출해야 함 ).

private void startCatcher() {
    UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();

    // the following handler is used to catch exceptions thrown in background threads
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler()));

    while (true) {
        try {
            Looper.loop();
            Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler);
            throw new RuntimeException("Main thread loop unexpectedly exited");
        } catch (Throwable e) {
            showCrashDisplayActivity(e);
        }
    }
}

보시다시피 포착되지 않은 예외 처리기는 백그라운드 스레드에서 발생한 예외에만 사용됩니다. 다음 핸들러는 이러한 예외를 포착하여 UI 스레드로 전파합니다.

static class UncaughtHandler implements UncaughtExceptionHandler {

    private final Handler mHandler;

    UncaughtHandler(Handler handler) {
        mHandler = handler;
    }

    public void uncaughtException(Thread thread, final Throwable e) {
        mHandler.post(new Runnable() {
            public void run() {
                throw new BackgroundException(e);
            }
        });
    }
}

이 기술을 사용하는 예제 프로젝트는 내 GitHub 저장소에서 사용할 수 있습니다. https://github.com/idolon-github/android-crash-catcher


FWIW I know this is slightly off-topic, but we've been using Crittercism's free plan with success. They also offer some premium features, like handling the exception so the app doesn't crash.

In the free version, the user still sees the crash, but at least I get the email and the stack trace.

We also use the iOS version (but I've heard from my colleagues that it is not quite as good).


Here are similar questions:


I think to disable that in your uncaughtException() method do not call previousHandler.uncaughtException() where previousHandler is set by

previousHandler = Thread.getDefaultUncaughtExceptionHandler();

It doesn't work until you call

android.os.Process.killProcess(android.os.Process.myPid());

at the very end of your UncaughtExceptionHandler.

참고URL : https://stackoverflow.com/questions/2764394/ideal-way-to-set-global-uncaught-exception-handler-in-android

반응형