使用自定义UncaughtExceptionHandler处理Firebase崩溃报告和自定义Application类

路易CAD

我的Android应用程序当前使用UncaughtExceptionHandler旨在捕获任何崩溃的自定义,并计划在将来重新启动应用程序几秒钟,AlarmManager然后手动调用Process.killProcess(Process.myPid())以避免Android的“强制关闭”弹出窗口,因为在我的应用程序用例中,用户将无法进行交互用设备在FC对话框上点击“确定”,然后重新启动应用程序。

现在,我想与Firebase Crash报告集成,但是我担心错误的行为,所以这是我的问题:

  1. 我应该如何编写代码,以便我的自定义项UncaughtExceptionHandler在杀死进程之前将异常传递给Firebase Crash Report?可以打电话Thread.getDefaultUncaughtExceptionHandler()给我Firebase崩溃报告,UncaughtExceptionHandler这样我就可以打电话uncaughtException(...)了吗?
  2. 可能会Process.killProcess(Process.myPid())阻止Firebase Crash报告库执行报告工作?Firebase在uncaughtException(...)返回之前是否会在单独的过程中启动崩溃报告Firebase是否会自己UncaughtExceptionHandler调用回Android默认值(UncaughtExceptionHandler显示FC对话框)?
  3. 可能Process.killProcess(Process.myPid())除了默认的进程杀死火力地堡崩溃报告的过程?
  4. 我的自定义Application如何检测是否在Firebase崩溃报告过程中实例化了它?以相同的方式对待这两个过程可能会导致状态不一致。

感谢任何试图帮助我的人!

路易CAD

经过一些测试,我终于找到了一种方法来确保我的应用在结束后能够正常重启UncaughtException我尝试了三种不同的方法,但是只有第一种,这是我的原始代码,仅Throwable作了一点点调整就将未捕获的信息传递给FirebaseCrash,并确保将其视为致命错误。

起作用的代码:

final UncaughtExceptionHandler crashShield = new UncaughtExceptionHandler() {

    private static final int RESTART_APP_REQUEST = 2;

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (BuildConfig.DEBUG) ex.printStackTrace();
        reportFatalCrash(ex);
        restartApp(MyApp.this, 5000L);
    }

    private void reportFatalCrash(Throwable exception) {
        FirebaseApp firebaseApp = FirebaseApp.getInstance();
        if (firebaseApp != null) {
            try {
                FirebaseCrash.getInstance(firebaseApp)
                        .zzg(exception); // Reports the exception as fatal.
            } catch (com.google.firebase.crash.internal.zzb zzb) {
                Timber.wtf(zzb, "Internal firebase crash reporting error");
            } catch (Throwable t) {
                Timber.wtf(t, "Unknown error during firebase crash reporting");
            }
        } else Timber.wtf("no FirebaseApp!!");
    }

    /**
     * Schedules an app restart with {@link AlarmManager} and exit the process.
     * @param restartDelay in milliseconds. Min 3s to let the user got in settings force
     *                     close the app manually if needed.
     */
    private void restartApp(Context context, @IntRange(from = 3000) long restartDelay) {
        Intent restartReceiver = new Intent(context, StartReceiver_.class)
                .setAction(StartReceiver.ACTION_RESTART_AFTER_CRASH);
        PendingIntent restartApp = PendingIntent.getBroadcast(
                context,
                RESTART_APP_REQUEST,
                restartReceiver,
                PendingIntent.FLAG_ONE_SHOT
        );
        final long now = SystemClock.elapsedRealtime();
        // Line below schedules an app restart 5s from now.
        mAlarmManager.set(ELAPSED_REALTIME_WAKEUP, now + restartDelay, restartApp);
        Timber.i("just requested app restart, killing process");
        System.exit(2);
    }
};
Thread.setDefaultUncaughtExceptionHandler(crashShield);

解释为什么和不成功的尝试

奇怪的是,reportFatal(Throwable ex)FirebaseCrash类中假设命名的方法在静止时(而且值得庆幸的是)保护了它的名称public,并为其赋予了以下签名:zzg(Throwable ex)

此方法应保持公开状态,但不要混淆恕我直言。

为了确保我的应用程序可以正常使用Firebase Crash Report库引入的多进程,我不得不按照Doug Stevenson的建议将代码从应用程序类中移开(这是一件好事),而是将其放入延迟加载的单例中。现在已准备好进行多进程。

您可以看到,在我的代码中没有地方我调用/委托给default UncaughtExceptionHandler,这里是Firebase Crash Reporting之一。我之所以没有这样做,是因为它总是调用默认值,即Android的默认值,它具有以下问题:

我将异常传递给Android默认值的那一行之后编写的所有代码UncaughtExceptionHandler将永远不会执行,因为该调用是阻塞的,并且进程终止是之后唯一发生的事情,除非已经运行了线程。

使应用程序终止运行并重启的唯一方法是在不久的将来编程方式System.exit(int whatever)Process.kill(Process.myPid())计划重新启动后终止该进程AlarmManager

鉴于此,我Thread在调用default之前开始了一个新操作UncaughtExceptionHandler,该操作将在Firebase Crash Reporting库获得异常但在计划的重启火灾(需要幻数)之前终止正在运行的进程它是第一次工作,在后台线程终止进程时删除了“强制关闭”对话框,然后AlarmManager唤醒了我的应用程序,让它知道它崩溃了并且有机会重新启动。

问题是第二次由于某些晦涩且完全没有记载的原因而没有工作即使安排调用的重新启动的代码AlarmManager已正确运行,该应用也永远不会重新启动

此外,“强制关闭”弹出窗口将永远不会显示。在看到是否包括Firebase Crash报告(因此自动启用)并没有改变此行为后,它与Android绑定(我在运行Android 4.4.2的Kyocera KC-S701上进行了测试)。

因此,我最终搜索了Firebase自己UncaughtExceptionHandler调用的东西,以报告可抛出的东西,并发现我可以自己调用代码并管理自己的应用程序在未捕获的情况下的行为Throwable

Firebase如何改善这种情况,使假想的命名reportFatal(Throwable ex)方法不被名称混淆和记录下来,或者让我们决定在Firebase抓住Throwable之后发生什么,UncaughtExceptionHandler而不是硬性地委派给笨拙的Android默认值,UncaughtExceptionHandler这将大有帮助。

它将允许开发人员开发在Android上运行的关键应用程序,以确保在用户无法运行的情况下确保其应用程序继续运行(考虑医疗监控应用程序,监控应用程序等)。

它还将允许开发人员启动自定义活动,以要求用户解释它是如何发生的,并具有发布屏幕截图等功能。

顺便说一句,我的应用程序旨在监视紧急情况下的人类福祉,因此无法忍受停止运行。必须恢复所有异常,以确保用户安全。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章