引言
最近发现一个偶发性bug,根据崩溃堆栈显示,在Service的onStartCommand方法中获取的intent对象为空。
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.getBooleanExtra(java.lang.String, boolean)' on a null object reference
首先需要明确两点:1、在Service启动的时候,的确传了Intent对象;2、这是一个偶发性的bug
代码分析
在Service的onStartCommand方法中有一个flag标志位,有如下取值:
START_STICKY
:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY
:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统将会把它置为started状态,系统不会自动重启该服务,直到startService(Intent intent)方法再次被调用;
START_REDELIVER_INTENT
:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入;
START_STICKY_COMPATIBILITY
:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
因为我所用的Service是需要利用Intent传递参数的,所有在Service被异常kill的时候,希望系统重启Service能把Intent的值页传进来。按常理来说,将标志位设置成START_REDELIVER_INTENT
应该就OK了。然而我貌似就是这样设置的,但是还是出现空指针异常。
在Stack Overflow上看到这样一段话:
Are you possibly confusing [START_FLAG_REDELIVERY](http://developer.android.com/reference/android/app/Service.html#START_FLAG_REDELIVERY) with [START_REDELIVER_INTENT](http://developer.android.com/reference/android/app/Service.html#START_REDELIVER_INTENT)? Your post says, "the return value START_FLAG_REDELIVERY ". That constant is not one of the values returned from [onStartCommand](http://developer.android.com/reference/android/app/Service.html#onStartCommand(android.content.Intent,%20int,%20int)), it is one of the bit values passed into onStartCommand as the flags parameter. START_FLAG_REDELIVERY and START_STICKY both have value of 1. If you mistakenly have return START_FLAG_REDELIVERY at the end of onStartCommand() , the service will restart in sticky mode with a null intent if there are no start commends pending.
有START_FLAG_REDELIVERY和START_REDELIVER_INTENT两个标志位,而且两个标志位代表的意思还不一样。这里粘贴一下Document里面的原文:
结论
保险起见,还是在传进来的Intent做一次判空