通過 startService 啓動的服務,一定會調用 service 的 onStartCommand 方法。
Service 源碼裏面,onStartCommand 方法的原型
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
而我們覆寫該方法是這樣的
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// todo
return super.onStartCommand(intent, flags, startId);
}
該方法有返回值,類型爲 int,而我們返回父類的 onStartCommand 結果,即:
START_STICKY_COMPATIBILITY 或者 START_STICKY。
那麼,到底返回哪個呢?還得看 mStartCompatibility 的值
mStartCompatibility =
getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR;
可以看出,只要我們的應用程序 targetSdkVersion 小於 2.0
那麼就返回 START_STICKY_COMPATIBILITY,否則返回 START_STICKY。
當然我們可以自己返回指定的值,不返回父類的結果。但是究竟可以返回哪些?
查看 api 文檔,關於 onStartCommand 的介紹
繼續跟蹤 START_CONTINUATION_MASK,會發現
START_STICKY
START_NOT_STICKY
START_REDELIVER_INTENT
START_STICKY_COMPATIBILITY
爲了,解釋這幾個 int 值的含義,除了結合 api 文檔(尼嘛,很難懂,有木有!),必須實踐。
原理:PlayerService -- > Runnable -- > run 製造異常,模擬系統殺死該進程。
在實驗之前,爲了確保實驗的準確性請做到 abcde
a. 將你的模擬器或者真機調整到 settings/application/running service 界面
b. 在每個實驗之前使用 adb uninstall mark.zhang 卸載這個應用程序,並確保 success
c. 使用 eclipse 直接 run 該應用程序或者命令行 adb install ×××.apk
d. 第一次出現下面提示框,點擊 Force close,稍等一會,再次看運行結果,打印信息
e. 再次出現上面對話框直接關閉,不用再等,服務只會自動重啓一次
------------------------------------------ start ---------------------------
1. START_STICKY
可以看出,再次調用 onCreate、onStartCommand,並且 startId = 2, 但是 intent = null
2. START_NOT_STICKY
這次並沒有重啓。
3. START_STICKY_COMPATIBILITY
只調用了oncreate 方法,沒有調用 onStartCommand
4. START_REDELIVER_INTENT
可以看出,再次調用 onCreate、onStartCommand,並且 startId = 1, 但是 intent 不爲 null
說明該 int 可以保留上次的 startId 與 intent
------------------------------------------ end ---------------------------
-------------- 附錄
PlayerActivity.java
package mark.zhang;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class PlayerActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onService(View view) {
Intent intent = new Intent(PlayerActivity.this, PlayerService.class);
startService(intent);
}
}
PlayerService.java
package mark.zhang;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class PlayerService extends Service {
private static final String TAG = "PlayerService";
private static final long DELAY = 2000;
private Handler sWork = new Handler();
private Runnable task = new Runnable() {
@Override
public void run() {
Log.d(TAG, DELAY / 1000 + "s after-----------");
// 故意製造異常,使該進程掛掉
Integer.parseInt("ok");
}
};
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind------");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate------");
sWork.postDelayed(task, 5000);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand------and startId = " + startId);
Log.d(TAG, "onStartCommand------and intent = " + intent);
// 實驗中,可輪換這幾個值測試
return START_NOT_STICKY;// | START_STICKY | START_STICKY_COMPATIBILITY |
// START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy------");
super.onDestroy();
}
}