我的Android应用程序当前使用UncaughtExceptionHandler
旨在捕获任何崩溃的自定义,并计划在将来重新启动应用程序几秒钟,AlarmManager
然后手动调用Process.killProcess(Process.myPid())
以避免Android的“强制关闭”弹出窗口,因为在我的应用程序用例中,用户将无法进行交互用设备在FC对话框上点击“确定”,然后重新启动应用程序。
现在,我想与Firebase Crash报告集成,但是我担心错误的行为,所以这是我的问题:
UncaughtExceptionHandler
在杀死进程之前将异常传递给Firebase Crash Report?可以打电话Thread.getDefaultUncaughtExceptionHandler()
给我Firebase崩溃报告,UncaughtExceptionHandler
这样我就可以打电话uncaughtException(...)
了吗?Process.killProcess(Process.myPid())
阻止Firebase Crash报告库执行报告工作?Firebase在uncaughtException(...)
返回之前是否会在单独的过程中启动崩溃报告?Firebase是否会自己UncaughtExceptionHandler
调用回Android默认值(UncaughtExceptionHandler
显示FC对话框)?Process.killProcess(Process.myPid())
除了默认的进程杀死火力地堡崩溃报告的过程?Application
类如何检测是否在Firebase崩溃报告过程中实例化了它?以相同的方式对待这两个过程可能会导致状态不一致。感谢任何试图帮助我的人!
经过一些测试,我终于找到了一种方法来确保我的应用在结束后能够正常重启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] 删除。
我来说两句