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

травня
11
2012
Мітки: android crash

Зміст

У другій частині статті про необроблені винятки в Android трохи розширимо логіку програми: будемо прокидати необроблене виключення далі щоб стандартний обробник обробив його, 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

< Як відловити необроблені виключення в Android

Напишіть перше повідомлення!

Ви повинні увійти під своїм аккаунтом щоб залишати коментарі