Serviced的onStartCommand方法有一個返回值,這個返回值告訴系統如果系統資源緊張,系統不得不關閉某些服務后,過一段時間,系統資源不那么緊張了的情況下,服務是否會重新啟動,以及以何種方式重新啟動。讓我們先來看一下onStartCommand方法:
以下分析基于API level 25的源碼
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
mStartCompatibility這個屬性的意思是啟動的時候是否是兼容模式。如果服務運行在低于ECLAIR(API level 5)的版本,那么這個值是true,否則這個值是false。當這個值是false的時候,這個方法返回的就是START_STICKY。
當我們從Service繼承一個自己的服務的時候,如果我們就調用Service類的onStartCommand方法的話,代碼就是這樣的:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
因為我們現在的android系統版本幾乎沒有低于ECLAIR的了。經過剛才的分析,super.onStartCommand(intent, flags, startId)方法的返回值就應該是START_STICKY。那么START_STICKY到底代表什么意思呢?
/**
* 這個常量是{@link #onStartCommand}方法的其中一個返回值:如果這個服務的進程在這個服務
* 已經啟動(也就是{@link #onStartCommand}方法已經運行完了)之后因為系統資源緊張等問
* 題被系統暫時關閉了,系統會記住這個服務剛才是正在運行的狀態,等到系統資源不那么緊
* 張的時候,系統會重新啟動這個服務的,但是系統不會把啟動這個服務的intent也保存下來。所以,過
* 段時間,系統嘗試重新啟動這個服務的時候,如果這個服務沒有收到其他讓它啟動的命令,那么這個
* 方法被系統調用的時候,intent參數就是null。所以,在使用的時候一定要注意。
*
* 這個模式一般用在啟動過后,運行一段時間,運行完了就結束的這種服務,比如在后臺播放音樂。
*/
public static final int START_STICKY = 1;
不要問我為什么我這里的注釋是中文的,這是我自己翻譯的
除此之外這個方法還有其他兩種可選的返回值:
/**
* 這個常量是{@link #onStartCommand}方法的其中一個返回值:如果這個服務的進程在這個服務
* 已經啟動(也就是{@link #onStartCommand}方法已經運行完了)之后因為系統資源緊張等問題
* 被系統關閉了,并且沒有新的intent來重新啟動這個服務的話,那么, 這個服務再也不會被啟動了。
*
* 這個模式是為了在服務中執行一些內存不夠的時候,也可以被中止的任務。這些任務通常過會兒
* 會被其他組件啟動的。比如從服務器上獲取數據:用定時器每隔幾分鐘啟動一次這個服務,在這個服
* 務里面啟動一個線程去做網絡請求。如果在做某次網絡請求的時候,這個服務所在的進程被終止了,
* 那么這個服務不會自己啟動,而是等到定時器下次的計時到了之后啟動它。
*/
public static final int START_NOT_STICKY = 2;
/**
* 這個常量是{@link #onStartCommand}方法的其中一個返回值:如果這個服務的進程在這個服務
* 已經啟動(也就是{@link #onStartCommand}方法已經運行完了)之后因為系統資源緊張等問題
* 被系統關閉了,這個服務會被系統用最近一次啟動這個服務所用的Intent重新啟動它。這個Intent
* 會被系統一直保存到{@link #stopSelf(int)}方法被調用為止。這種情況下,服務當中的
* {@link #onStartCommand(Intent, int, int)}里面的intent不會是null。因為這種服務只
* 會在所有啟動它的intent都執行完了的情況下才不會重新啟動。
*/
public static final int START_REDELIVER_INTENT = 3;
所以,仔細甄別一下,如果你使用的時候發現intent為null,有可能你需要的是START_REDELIVER_INTENT這種啟動方式。