내 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
답변
uncaughtException () 메서드에서 previousHandler가 설정된 previousHandler.uncaughtException ()을 호출하지 않는 것을 비활성화한다고 생각합니다.
previousHandler = Thread.getDefaultUncaughtExceptionHandler();
답변
FWIW 나는 이것이 약간 주제에서 벗어난 것을 알고 있지만 우리는 크 리터 시즘의 무료 계획 을 성공적으로 사용하고 있습니다. 또한 앱이 충돌하지 않도록 예외 처리와 같은 몇 가지 프리미엄 기능을 제공합니다.
무료 버전에서는 사용자에게 여전히 충돌이 표시되지만 적어도 이메일과 스택 추적을받습니다.
우리는 또한 iOS 버전을 사용합니다 (하지만 제 동료들로부터 그다지 좋지 않다고 들었습니다).
다음은 비슷한 질문입니다.
답변
전화 할 때까지 작동하지 않습니다.
android.os.Process.killProcess(android.os.Process.myPid());
UncaughtExceptionHandler의 맨 끝에.
답변
