我有一个简单的设置:
CrashHandler
- 一个实现的类Thread.UncaughtExceptionHandler
;CrashActivity
- 可以发送用户报告的活动;MainActivity
- 用户应该与之交互的主应用程序。
MainActivity
当线程或任何线程中存在未捕获的异常时,CrashHandler
拦截它并创建一个通知以启动CrashActivity
:
Intent it = new Intent("CrashReporter" + SystemClock.currentThreadTimeMillis());
it.setClass(context, CrashActivity.class);
it.setFlags(it.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
与此同时,Android 显示“应用程序崩溃”消息,用户单击确定,应用程序关闭,然后用户可能会单击notification
. 如果notification
单击 ,则CrashActivity
启动并显示。
这段代码已经在许多不同的情况下工作了很长时间(主线程崩溃, ahandler
崩溃,后台崩溃thread
......)。但是,我最近发现,如果在OnClickListener.onClick
附加button
到MainActivity
. 情况如下:
- 我执行的代码故意抛出
NullPointerException
; CrashHandler
拦截它并创建一个notification
(如图所示);- Android 不显示任何消息(例如,没有“应用程序崩溃”,应该是可见的);
- 被
MainActivity
冻结; - 如果用户单击通知以启动
CrashActivity
,则会显示黑屏并且一切都冻结(未显示所需的活动)。
Logcat
表明启动有超时,甚至在OnCreate
我的代码之前或任何代码之前:
I/ActivityManager(11826): START u0 {act=CrashHandler1196 flg=0x14000000 cmp=mycompany.myapp/.CrashActivity bnds=[0,102][720,230] (has extras)} from pid -1
W/KeyguardViewMediator(11826): verifyUnlock called when not externally disabled
W/ActivityManager(11826): Activity pause timeout for ActivityRecord{41f4d988 u0 mycompany.myapp/.MainActivity}
W/ActivityManager(11826): Launch timeout has expired, giving up wake lock!
W/ActivityManager(11826): Activity idle timeout for ActivityRecord{4225eeb8 u0 mycompany.myapp/.CrashActivity}
- 如果在单击
notification
I kill the app from之前ADB
,notification
效果很好。 如果在点击之前
notification
我在冻结的应用程序上做了一些点击和手势,几秒钟后我收到一条消息ANR
:E/ActivityManager(11826): ANR in mycompany.myapp (mycompany.myapp/.MainActivity) E/ActivityManager(11826): Reason: keyDispatchingTimedOut E/ActivityManager(11826): Load: 0.63 / 0.57 / 0.49
如果我单击“是,杀死它”,然后单击
notification
,它可以完美运行。- 如果我在创建通知后添加
System.exit
(-1)CrashHandler
,应用程序会立即退出并且通知工作正常(不幸的是,我无法在生产中使用此解决方案)。
我有两个问题:
- 为什么一个
NullPointer exception
inOnClickListener.onClick
不会导致应用程序崩溃,而是将其与操作系统一起冻结并阻止其他活动启动? - 一般来说,如何避免它,或者至少,如何
CrashActivity
在这些条件下开始?