UncaughtExceptionHandler를 이용한 앱 비정상 종료시 Log전송 및 재실행 하기

UncaughtExceptionHandler를 이용한 앱 비정상 종료시 Log전송 및 재실행 하기






요즘 앱을 보면 앱실행중 Exception이 발생하면 앱이 종료 되었다가 재 실행 되는것을 볼 수 있다. 어떻게 앱이 비정상 종료되는 순간을 Catch한것일까?


 


방법은 UncaughtExceptionHandler를 이용하면 된다.






보통 Thread는 try{} catch(Exception e){}외에 발생 하는 예외는 UncaughtExceptionHandler의 uncaughtThread(Thead thread, Throwable ex)를 호출 하게 되어 있다. 그래서 Thread의 UncaughtExceptionHandler 인스턴스를 Thread에 등록하면 되는데, Thread의 static메소드인 setDefaultUncaughtExceptionHandler()를 이용하여 UncaughtExceptionHandler를 set할 수 있다. 






이렇게 하면 별도로 예외처리 하지 않은 부분에서 예외가 발생 하게되면 uncaughtThread(Thead thread, Throwable ex)가 호출되어 유용한 작업들을 할 수있다.




그럼 간략하게 구현 해보자.




import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;

import android.app.Application;
import android.util.Log;

public class MyApplication extends Application {

private UncaughtExceptionHandler mUncaughtExceptionHandler;

@Override
public void onCreate(){

    mUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlerApplication());

    super.onCreate();
}

/**
 * 메시지로 변환
 * @param th
 * @return
 */
private String getStackTrace(Throwable th) {

    final Writer result = new StringWriter();
    final PrintWriter printWriter = new PrintWriter(result);

    Throwable cause = th;
    while (cause != null) {
        cause.printStackTrace(printWriter);
        cause = cause.getCause();
    }
    final String stacktraceAsString = result.toString();
    printWriter.close();

    return stacktraceAsString;
}

class UncaughtExceptionHandlerApplication implements Thread.UncaughtExceptionHandler{

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {

        //예외상황이 발행 되는 경우 작업
        Log.e("Error", getStackTrace(ex)); 

        //예외처리를 하지 않고 DefaultUncaughtException으로 넘긴다.
        mUncaughtExceptionHandler.uncaughtException(thread, ex);
    }

}

}




안드로이드에서 Application onCreate()에서 Thread.setDefaultUncaughtExceptionHandler를 구현해주면 끝이다.




예외 상황 발생시 AlarmManager로 앱을 재 실행 하던가, 로그를 저장해두었다가 앱이 재 실행 되면 서버로 전송하는 기능을 구현하면 될 듯 하다.


실제로 ACRA이라는 버그리포팅 해주는 라이브러리가 이런 방법으로 구현 되어 있다. 




레퍼런스도 참고 하기 바란다.


http://developer.android.com/reference/java/lang/Thread.UncaughtExceptionHandler.html