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


88

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

Thread.setDefaultUncaughtExceptionHandler(
                new DefaultExceptionHandler(this));

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

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

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


1
같은 코드를 공유해 주
시겠습니까

2
예외를 기록하려면 acra.ch를 살펴 보십시오 . ACRA를 사용하면 오류 보고서를 Google-Doc 또는 이메일을 통해 사용자에게 보낼 수 있습니다.
Alexander Pacha

1
@Alexander가 아니면 그냥 ... 안드로이드에 대한 Google 웹 로그 분석을 사용하고, 당신이 원하는 모든 예외를 로그인 할 수 있습니다
IgorGanapolsky

이있을 수 있습니다 도움말 stackoverflow.com/questions/19897628/...
귀족 마이클

답변:


24

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

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

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


10
"오류를 처리 한 후 충돌을 일으키기 위해 포착되지 않은 예외를 던지는 것"은 여전히 ​​중요합니다. 방금 경험했습니다. 예외를 처리 한 후 내 앱이 잠 겼고 포착되지 않은 예외가 발생하지 않았습니다.
OneWorld

@OneWorld Jepp은 여기서도 마찬가지입니다. 적어도 잠금 부분에서는 앱이 충돌하지 않도록 "저장"할 방법이없는 것 같습니다.
AgentKnopf

@Zainodis 나는 크 리터 시즘에 대한 링크를 제공하는이 질문에 약간의 주제에서 벗어난 답변을 게시했습니다. 앱이 결국 충돌하는 것을 "저장"할 수있는 기능이 있다고 생각합니다. 확실하지 않음-무료 버전 atm 만 사용하고 있습니다.
리처드 르 Mesurier

@RichardLeMesurier 힌트 주셔서 감사합니다-내가 확인해 볼게 :)!
AgentKnopf

이상한!!! 내 활동에서 예외를 처리하더라도 uncaughtexception이 호출됩니다. 어떤 생각.
Hiren Dabhi

12

오래 전에 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


짐작할 수 있듯이 이렇게하면 사용자 지정 오류 대화 상자를 표시 할 수있을뿐만 아니라 사용자가 예외를 무시하고 애플리케이션 작업을 계속할 수 있습니다 (게시 된 앱에는 좋지 않은 생각처럼 보이지만 디버그 또는 테스트 세션 중에 매우 편리합니다.)
Idolon 2015 년

안녕하세요, 이것은 잡히지 않은 예외를 잡는 데 작동하지만 어떤 이유로이 코드는 항상 예외를 던집니다. 처음에는 startCatcher 메서드에있는 RuntimeException 줄 때문 이었지만 제거 후에도 여전히 예외가 발생합니다. 그것이 필요한지 확실하지 않습니다. 어쨌든 내가 얻는 예외는 java.lang.RuntimeException: Performing pause of activity that is not resumed. 내 루퍼를 시작하려고 할 때 시스템이 시작하려는 활동을 일시 중지한다고 생각합니까? 확실하지 않지만 어떤 도움을 주시면 감사하겠습니다. 감사합니다
sttaq

또한 startCatcher를 제거하면 즉, 코드없이 앱을 실행하면 예외없이 모든 것이 잘 작동합니다.
sttaq

@sttaq 어떤 버전의 Android를 사용하십니까?
Idolon

2.3.x에서 시도한 것 같습니다
sttaq

3

uncaughtException () 메서드에서 previousHandler가 설정된 previousHandler.uncaughtException ()을 호출하지 않는 것을 비활성화한다고 생각합니다.

previousHandler = Thread.getDefaultUncaughtExceptionHandler();

2

FWIW 나는 이것이 약간 주제에서 벗어난 것을 알고 있지만 우리는 크 리터 시즘의 무료 계획 을 성공적으로 사용하고 있습니다. 또한 앱이 충돌하지 않도록 예외 처리와 같은 몇 가지 프리미엄 기능을 제공합니다.

무료 버전에서는 사용자에게 여전히 충돌이 표시되지만 적어도 이메일과 스택 추적을받습니다.

우리는 또한 iOS 버전을 사용합니다 (하지만 제 동료들로부터 그다지 좋지 않다고 들었습니다).


다음은 비슷한 질문입니다.


1

전화 할 때까지 작동하지 않습니다.

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

UncaughtExceptionHandler의 맨 끝에.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.