Необработанные исключения (UncaughtExceptionHandler) в Android. Часть 2

мая
11
2012
Метки: android crash

Содержание

Во второй части статьи об необработанных исключениях немного расширим логику приложения: будем пробрасывать необработанное исключения далее чтобы стандартный обработчик обработал его, stacktrace исключения отсылается на указанный адрес и если приложение не может отослать данные, то автоматически выключается через 10 секунд.

Приступим к первому пункуту - добавим проброс необработанного исключения стандартному обработчику. Для этого в Вашем activity объявите экземпляр класса Thread.UncaughtExceptionHandler:


Thread.UncaughtExceptionHandler defaultExceptionHandler;

Затем в методе onCreate() Вашего activity сохраните обработчик исключений по умолчанию в эту переменную перед установкой нового обработчика:


@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	
	defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
	Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
	
        // ...
}

А в обработчике необработанных исключений добавьте вызов метода uncaughtException() объекта defaultExceptionHandler:


defaultExceptionHandler.uncaughtException(t, e);

Файл activity целиком:


package com.seostella.catchcrashreport;

import android.app.Activity;
import android.os.Bundle;

public class CatchCrashReportActivity extends Activity {
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
		defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
        
        int a = 1;
        a--;
        int b = 10 / a;
    }
    
    Thread.UncaughtExceptionHandler defaultExceptionHandler;
    Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {

        @Override
        public void uncaughtException(Thread t, Throwable e) {
        	e.printStackTrace();
        	// do something
        	
        	defaultExceptionHandler.uncaughtException(t, e);
        }
    };
    
}

Второй пункт - отсылка информации о исключении на сервер. Описывать непосредственно отсылку сообщения мы не будем так как работа с сетью выходит за границы этой статьи. Подготовим лишь объект для отсылки. Для этого измените метод uncaughtException() следующим образом:


@Override
public void uncaughtException(Thread t, Throwable e) {
	e.printStackTrace();
	// do something
	
	final Writer result = new StringWriter();
	final PrintWriter printWriter = new PrintWriter(result);
	e.printStackTrace(printWriter);
	String stacktrace = result.toString();
	printWriter.close();
	
	// send stacktrace data 
	
	defaultExceptionHandler.uncaughtException(t, e);
}

Этим кодом мы создаем строковую переменную stacktrace с информацией об исключении.

И, наконец, автозавершение программы если она не завершилась сама через 10 секунд после исключения. Тут всё просто: в Ваш activity добавьте следующий метод:


public void startExitChecker(){
	new Thread(){
		private static final long WAIT_TIME = 10000;
		private static final long SMALL_WAIT_TIME = 1000;
		
		public void run(){
			try{
				long startTime = System.currentTimeMillis();
				boolean forceClose = true;
				while( System.currentTimeMillis() - startTime < WAIT_TIME ){
					try {
						Thread.sleep( SMALL_WAIT_TIME );
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if( CatchCrashReportActivity.this == null ){
						forceClose = false;
						break;
					}
				}
				if( forceClose ){
					CatchCrashReportActivity.this.finish();
				}
			} catch( Exception e ){
			}
		}
	}.start();
} 

Вызов этого метода необходимо поместить в метод uncaughtException() перед вызовом обработчика исключений по умолчанию. То есть, метод uncaughtException() выглядит следующим образом:


@Override
public void uncaughtException(Thread t, Throwable e) {
	e.printStackTrace();
	// do something
	
	final Writer result = new StringWriter();
	final PrintWriter printWriter = new PrintWriter(result);
	e.printStackTrace(printWriter);
	String stacktrace = result.toString();
	printWriter.close();
	
	// send stacktrace data 
	startExitChecker();
	defaultExceptionHandler.uncaughtException(t, e);
}

Приложение, демонстрирующее приведенные примеры можно скачать по следующей ссылке - Скачать CatchCrashReport.zip

< Как отловить необработанные исключения (Force close) в Android

Напишите первое сообщение!

Вы должны войти под своим аккаунтом чтобы оставлять комментарии