引言
最近發(fā)現(xiàn)一個偶發(fā)性bug,根據(jù)崩潰堆棧顯示,在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、這是一個偶發(fā)性的bug
代碼分析
在Service的onStartCommand方法中有一個flag標志位,有如下取值:
START_STICKY
:如果service進程被kill掉,保留service的狀態(tài)為開始狀態(tài),但不保留遞送的intent對象。隨后系統(tǒng)會嘗試重新創(chuàng)建service,由于服務狀態(tài)為開始狀態(tài),所以創(chuàng)建服務后一定會調(diào)用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那么參數(shù)Intent將為null。
START_NOT_STICKY
:“非粘性的”。使用這個返回值時,如果在執(zhí)行完onStartCommand后,服務被異常kill掉,系統(tǒng)將會把它置為started狀態(tài),系統(tǒng)不會自動重啟該服務,直到startService(Intent intent)方法再次被調(diào)用;
START_REDELIVER_INTENT
:重傳Intent。使用這個返回值時,如果在執(zhí)行完onStartCommand后,服務被異常kill掉,系統(tǒng)會自動重啟該服務,并將Intent的值傳入;
START_STICKY_COMPATIBILITY
:START_STICKY的兼容版本,但不保證服務被kill后一定能重啟。
因為我所用的Service是需要利用Intent傳遞參數(shù)的,所有在Service被異常kill的時候,希望系統(tǒng)重啟Service能把Intent的值頁傳進來。按常理來說,將標志位設置成START_REDELIVER_INTENT
應該就OK了。然而我貌似就是這樣設置的,但是還是出現(xiàn)空指針異常。
在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里面的原文:
結(jié)論
保險起見,還是在傳進來的Intent做一次判空