引言

最近发现一个偶发性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里面的原文:

eae3eed44579?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Android Develop截图

结论

保险起见,还是在传进来的Intent做一次判空

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐