Rethrow UncaughtExceptionHandler Исключение после регистрации - PullRequest
6 голосов
/ 29 января 2012

В моем классе Application я пытаюсь поймать силу близко до того, как это произойдет, поэтому я могу войти в систему, а затем сбросить ее, чтобы android мог справиться с этим.Я делаю это, так как некоторые пользователи не сообщают о принудительном закрытии.

Я развиваюсь в затмении, и затмение не позволяет мне отбросить исключение.Он показывает сообщение об ошибке «Необработанный тип исключения Throwable: Surround с try / catch».Как я могу отбросить исключение?

public class MainApplication extends Application
{
    @Override
    public void onCreate()
    {
    super.onCreate();

    try
    {
        //Log exception before app force closes
        Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
                        "Errors",                       // Category
                        "MainActivity",                 // Action
                        "Force Close: "+ex.toString(),  // Label
                        0);                             // Value
                AnalyticsUtils.getInstance(MainApplication.this).dispatch();

                Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);

                //rethrow the Exception so user can report it
                //throw ex; //<-- **eclipse is showing an error to surround with try/catch**
            }
        });

    } catch (Exception e)
    {
        e.printStackTrace();
    }
}

}

Ответы [ 4 ]

13 голосов
/ 29 января 2012

Извинения, не эксперт по Android - но похоже, что вы не можете выбросить ex, потому что сигнатура вашего метода "void uncaughtException (Thread, Throwable)" не объявляет, что она "выбрасывает" что-либо.

Предполагая, что вы переопределяете интерфейс API и (а) не можете изменить эту подпись и (б) не хотите, потому что вы бы выбросили ее из контекста, могли бы вы вместо этого использовать шаблон декоратора и в основном подкласс реализации UncaughtExceptionHandler по умолчанию для регистрации вашего сообщения, а затем позволить ему продолжить обработку как обычно?

Редактировать: не проверено, но это может выглядеть примерно так:

    final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
    Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            // your code 
            AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
                    "Errors",                       // Category
                    "MainActivity",                 // Action
                    "Force Close: "+ex.toString(),  // Label
                    0);                             // Value
            AnalyticsUtils.getInstance(MainApplication.this).dispatch();
            Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG).show();

            // carry on with prior flow
            subclass.uncaughtException(thread, ex);
        }
    });
0 голосов
/ 14 марта 2019

Для тех, кто находит этот вопрос только сейчас, я не уверен, что какой-либо из приведенных выше ответов был правильным при публикации, но это не так. В настоящее время вы хотите создать новый класс, который реализует Thread.UncaughtExceptionHandler, а в конструкторе сохранить Thread.getCurrentUncaughtExceptionHandler() в поле, и вы вызываете его uncaughtException(Thread, Throwable) в конце your uncaughtException(Thread, Throwable) метод. Затем вы вызываете Thread.setUncaughtExceptionHandler() из любого кода, создающего экземпляр вашего класса, часто MainApplication.onCreate.

Таким образом, полный код будет выглядеть примерно так:

//MainApplication.java
public class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        CustomUncaughtExceptionHandler cueh = new CustomUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(cueh);
    }
}

//CustomUncaughtExceptionHandler.java
class CustomUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler oldHandler;

    CustomUncaughtExceptionHandler() {
        oldHandler = Thread.getDefaultUncaughtExceptionHandler();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
                "Errors",                       // Category
                "MainActivity",                 // Action
                "Force Close: "+ex.toString(),  // Label
                0);                             // Value
        AnalyticsUtils.getInstance(MainApplication.this).dispatch();
        if (oldHandler != null) {
            oldHandler.uncaughtException(thread, ex);
        else {
            System.exit(1);
        }
    }
}

Вы также можете сохранить исходный обработчик необработанных исключений по умолчанию где-нибудь еще для восстановления позже (или добавить метод getOldHandler()), если по какой-либо причине вы решите, что ваш код больше не будет выполняться.

0 голосов
/ 07 марта 2013

Я думаю, что следующий код должен работать.Выполнение кода обработчика с использованием нового потока позволяет приложению показывать предупреждение / тост и выполнять другие операции.

Кроме того, вы можете попробовать вызвать System.exit(0) непосредственно перед выходом run().Это возобновляет последнюю активность.

Я проверял это как на Имбирном хлебе , так и на Желейных бобах .

final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
    Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            new Thread() {
                @Override
                public void run() {
                    Looper.prepare();  
                    // your code 
                    AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
                            "Errors",                       // Category
                            "MainActivity",                 // Action
                            "Force Close: "+ex.toString(),  // Label
                            0);                             // Value
                    AnalyticsUtils.getInstance(MainApplication.this).dispatch();
                    Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);

                    Looper.loop();
                }
            }.start();
        }
    });
0 голосов
/ 29 января 2012

Я не совсем уверен, что это именно то, что вам нужно, однако вы можете добавить предложение finally, которое будет выполняться после успешного try или обработанного catch:

try {
    //your code
} catch (Exception e) {
    //print stack trace
} finally {
    //Log
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...