通知栏出现ANR原因

时间:2022-08-30 17:06:29

有的时候,我们不断的发一个通知,如果次数达到定后,可能会导致通知栏消失(3.0以下的Android system),这个问题,其实是Android内部的一个Bug,下面我来分析一下造成这个问题的原因。

一,原因

当这个问题出现的时候,我们通过分析Log后得知,com.android.systemui进行中出现在ANR,原因就是处理广播消息时超时,而这个ANR会导致com.android.systemui进程死掉。

通常,状态栏会维护通知信息,并会保持所有通知的remote views,如果当一个客户端程序不断的发送通知的话,系统就不地断的使用内存来创建这些remote view,

因此,就会导致垃圾回收器(GC)开始回收内存,UI开始变慢(通俗一点说就是变卡),如果此时客户端程序还不断的发通知,那么UI会变得越来越慢,最后,ANR错误出现了。

我们可以写一个DEMO来重现这个问题,起一个timer,不断的发送通知,可能状态栏就会消失,此时的LOG如下: 

D/dalvikvm(11985): GC_EXPLICIT freed 1258 objects / 84016 bytes in 1157ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 52216 objects / 1900968 bytes in 130ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 49465 objects / 1805248 bytes in 125ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 53106 objects / 1909992 bytes in 134ms
...

12-10 15:07:11.088 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.098 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.098 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.098 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.108 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.128 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.128 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.138 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!
12-10 15:07:11.158 E/JavaBinder( 2240): !!! FAILED BINDER TRANSACTION !!!

从这个LOG中可以看见,GC不断的释放内存,这会导致UI响应延迟。

这种现象可以Android 2.1, 2.2, 2.3上面重现,3.0以上的我没有试过,不知道是不是存在同样的问题。当Notification bar中的RemoteView增长到一定数量之后,

也就是说它超过了IBinder.transcat()所能处理的范围,RemoteException异常就会抛出,有时候,如果起过了VM的限制,APP都可能会挂掉。

二,解决方案

关于这个问题,原因我们是知道了,如何解决。

我们不要去每次发送通知,我们可以用相同的消息ID去更新通知,而不是重新创建。

三,其他链接

这个问题,其实已经在Google的论坛上提出来了,可以参考:

http://code.google.com/p/android/issues/detail?id=13941通知栏出现ANR原因

http://code.google.com/p/csipsimple/issues/detail?id=676通知栏出现ANR原因