Crashlytics Android SDK — пользовательский UncaughtExceptionHandler

Можно ли включить пользовательский UncaughtExceptionHandler вместе с крашлитикой в ​​одно приложение? Если да - как?


person jskierbi    schedule 08.08.2014    source источник
comment
повезло с этим? Я также столкнулся с той же проблемой с новой реликвией. обнаружил, что код не смог дальше сцепить неперехваченное исключение.   -  person Seph Remotigue    schedule 13.10.2014
comment
@SephRemotigue попробуйте это решение stackoverflow.com/a/56990688/6445611   -  person Александр Кундрюков    schedule 11.07.2019


Ответы (6)


Поскольку последние версии Crashlytics выполняют инициализацию асинхронно, лучше использовать обратный вызов инициализации Fabric:

private static Thread.UncaughtExceptionHandler mDefaultUEH;
private static Thread.UncaughtExceptionHandler mCaughtExceptionHandler = 
   new Thread.UncaughtExceptionHandler() {
     @Override 
public void uncaughtException(Thread thread, Throwable ex) {
        // Custom logic goes here

        // This will make Crashlytics do its job
        mDefaultUEH.uncaughtException(thread, ex);
    }
};

CrashlyticsCore core = new CrashlyticsCore.Builder()
            .disabled(BuildConfig.DEBUG)
            .build();
Fabric.with(new Fabric.Builder(this).kits(new Crashlytics.Builder()
            .core(core)
            .build())
            .initializationCallback(new InitializationCallback<Fabric>() {
                @Override
                public void success(Fabric fabric) {
                    mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
                    Thread.setDefaultUncaughtExceptionHandler(mCaughtExceptionHandler);
                }

                @Override
                public void failure(Exception e) {

                }
            })
            .build());
person kmityak    schedule 13.03.2018
comment
Из того, что я вижу в CrashlyticsCore (v2.9.4), CrashlyticsController.enableExceptionHandling() вызывается внутри onPreExecute(). Так что это все еще делается в том же потоке. Также CrashlyticsUncaughtExceptionHandler (который использует контроллер) гарантирует, что он передает исключение любому существующему обработчику по умолчанию. Таким образом, порядок инициализации Fabric и вашего собственного обработчика исключений не имеет значения, если вы делаете то же самое. - person black; 06.08.2018
comment
Я попробовал это в своем классе приложений, в моем случае сбой (исключение e) получает обратный вызов с исключением: com.crashlytics.sdk.android.crashlytics-core Инициализация была отменена. Любые идеи, почему это происходит? - person Rahul Gurnani; 10.10.2018
comment
Я пытаюсь это сделать, но InitializationCallback не вызывается. Любые идеи? - person Blitz; 16.01.2019

ОБНОВЛЕНИЕ

См. @kmityak ответ, так как инициализация Crashlytics/Fabric теперь асинхронна, и мое решение, приведенное ниже, больше не действует.

ИСХОДНЫЙ ОТВЕТ

Вы можете настроить свой собственный UncaughtExceptionHandler при условии, что он будет передавать исключение в UncaughtExceptionHandler по умолчанию, который будет обрабатываться позже через Crashlytics.

Ниже код реализован внутри подкласса Application:

private static Thread.UncaughtExceptionHandler mDefaultUEH;
private static Thread.UncaughtExceptionHandler mCaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
    @Override 
    public void uncaughtException(Thread thread, Throwable ex) {
        // Custom logic goes here

        // This will make Crashlytics do its job
        mDefaultUEH.uncaughtException(thread, ex);
    }
};

@Override
public void onCreate() {
    super.onCreate();

    // Order is important!
    // First, start Crashlytics
    Crashlytics.start(this);

    // Second, set custom UncaughtExceptionHandler
    mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    Thread.setDefaultUncaughtExceptionHandler(mCaughtExceptionHandler);
}

Второй вариант — зарегистрировать Crashlytics после установки своего пользовательского UncaughtExceptionHandler — тогда все неперехваченные исключения будут сообщены Crashlytics как фатальные, а затем переданы вашему пользовательскому обработчику.

person jskierbi    schedule 13.10.2014
comment
Я не получаю метод Crashlytics.start(this). Я использую crashlytics:2.5.1. Я просто хочу выйти из своего приложения, а также отправить отчет в Fabric. Как я могу это сделать? - person SweetWisher ツ; 31.08.2015
comment
используйте Fabric.with(this, Crashlytics()) вместо Crashlytics.start(this) - person Tej; 07.09.2017
comment
Не могли бы вы сказать мне, где именно находится код? Я не понимаю, что имеется в виду под ... inside Application subclass. Благодарю вас! - person Mr. B.; 12.10.2017
comment
Вам нужно создать собственный класс Applicaiton. Вы можете сделать это, создав подкласс android.app.Application и зарегистрировав его в AndroidManifest.xml. Дополнительная информация здесь: developer.android.com/reference/android/app/Application. html - person jskierbi; 16.10.2017

Да, это возможно.

В вашем классе приложения:

@Override
public void onCreate() {
    super.onCreate();
    Crashlytics.start(this);
    initUncaughtExceptionHandler();
}

private void initUncaughtExceptionHandler() {
    final ScheduledThreadPoolExecutor c = new ScheduledThreadPoolExecutor(1);
    c.schedule(new Runnable() {
        @Override
        public void run() {
            final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                    // do my amazing stuff here 
                    System.err.println("Error!");
                    //then pass the job to the previous handler
                    defaultHandler.uncaughtException(paramThread, paramThrowable);
                }
            });
        }
    }, 5, TimeUnit.SECONDS);
}

Причина, по которой я планирую это через 5 секунд, заключается в том, что Crashlytics нужно некоторое время, чтобы настроить свои вещи. Я использую этот код, и он отлично работает. Конечно, если ваше приложение вылетает при запуске, извините, но нет специального обработчика;)

person Manza    schedule 15.10.2014

Нет, если эти решения сработали для меня. Я сделал это следующим образом:

// Setup handler for uncaught exceptions.
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
    @Override
    public void uncaughtException (Thread thread, Throwable e)
    {
        //Send Report to Crashlytics. Crashlytics will send it as soon as it starts to work
        Crashlytics.logException(e);

        //Your custom codes to Restart the app or handle this crash
        HandleCrashes(thread, e);
    }
});

А вот мой пользовательский метод для перезапуска приложения:

private void HandleCrashes(Thread t, Throwable e) {

    Intent i = new Intent(mContext, frmLogin.class);
    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    i.putExtra("JustLogin", true);
    startActivity(i);

    System.exit(1);
}
person user3682694    schedule 16.03.2015
comment
Проблема этого решения заключается в том, что Crashlytics сообщит об этом сбое как о нефатальном, а не об общем сбое. - person Vito Valov; 05.07.2015
comment
@VitoValov есть ли способ обойти это? по-прежнему отправлять как фатальный сбой, а также перезапустить приложение? - person Guillaume; 04.07.2017

  1. Отключить автоматический сбор

    добавь это в свой AndroidManifest.xml

<meta-data
     android:name="firebase_crashlytics_collection_enabled"
     android:value="false" />
  1. Зарегистрируйте свой клиент UncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(customerUncaughtExceptionHandler)
  1. Запуск Crashlytics вручную после регистрации UncaughtExceptionHandler
Fabric.with(this, new Crashlytics());
  1. пересоберите и переустановите приложение
person Suen    schedule 03.03.2020

Я нашел решение для Fabric 2.10.1:

Thread.setDefaultUncaughtExceptionHandler(yourExceptionHandler)
Fabric.with(this, Crashlytics())
person Александр Кундрюков    schedule 11.07.2019