当 OnClickListener.onClick 中出现 NullPointerException 时 Android 冻结(其他任务无法启动)

Posted

技术标签:

【中文标题】当 OnClickListener.onClick 中出现 NullPointerException 时 Android 冻结(其他任务无法启动)【英文标题】:Android freezes when there is a NullPointerException in OnClickListener.onClick (other tasks cannot start) 【发布时间】:2013-03-30 10:58:26 【问题描述】:

我有一个简单的设置:

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。如果单击notificationCrashActivity 将启动并显示。

这段代码已经在许多不同的情况下工作了很长时间(主线程崩溃,handler 崩溃,后台thread 崩溃......)。但是,我最近发现,如果在附加到MainActivity 中的button 的侦听器中的OnClickListener.onClick 方法中抛出异常,则它不起作用。情况如下:

    我执行的代码故意抛出NullPointerExceptionCrashHandler 拦截它并创建一个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 ActivityRecord41f4d988 u0 mycompany.myapp/.MainActivity
W/ActivityManager(11826): Launch timeout has expired, giving up wake lock!
W/ActivityManager(11826): Activity idle timeout for ActivityRecord4225eeb8 u0 mycompany.myapp/.CrashActivity
如果在单击notification 之前我从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,就完美了。

如果我在创建通知后在CrashHandler 中添加System.exit(-1),应用程序会立即退出并且通知工作正常(不幸的是,我无法在生产中使用此解决方案)。

我有两个问题:

    为什么OnClickListener.onClick 中的NullPointer exception 不会导致应用崩溃,而是将其与操作系统一起冻结并阻止其他活动启动? 一般要怎么做才能避免它,或者至少,如何使CrashActivity 在这些条件下启动?

【问题讨论】:

我认为您应该发布一些来自 onClick 的代码,以便我们理解。 【参考方案1】:

没有看到你的代码,你应该调试你的 CrashHandler 类。 JVM 将忽略此中的所有异常

void uncaughtException(Thread t, Throwable e)

“Java 虚拟机将忽略此方法引发的任何异常。” (JavaDoc)。

我说这不是答案,但如果此方法引发异常,它可能是答案。

【讨论】:

【参考方案2】:

为什么你不能杀死你自己的应用程序进程 https://developer.android.com/reference/android/os/Process.html#sendSignal(int, int)?

【讨论】:

以上是关于当 OnClickListener.onClick 中出现 NullPointerException 时 Android 冻结(其他任务无法启动)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DialogInterface.OnClickListener.onClick() 中获取 Activity 上下文?

当幸福来敲门英文PPT相关素材

python当密码正确输入,当密码错误时

更新:为啥当用户是管理员时关系有效,但当普通用户时不会?

当位于顶级栏目显示下级栏目,当位于二级栏目显示同级栏目,当位于三级目录,显示上级栏目

当应用程序在后台时扫描外围设备(例如,当屏幕锁定时)