Service概念及用途:
A service is an application component that can perform long-running operations in the background and does not provide a user interface。
通常service用來執行一些耗時操作,或者後臺執行不提供用戶交互界面的操作,例如:下載、播放音樂。
Service生命週期 :
Android Service的生命週期並不像Activity那麼複雜,它只繼承了onCreate(),onStart(),onDestroy()三個方法,當我們第一次啓動Service時,先後調用了onCreate(),onStart()這兩個方法,當停止Service時,則執行onDestroy()方法,這裏需要注意的是,如果Service已經啓動了,當我們再次啓動Service時,不會在執行onCreate()方法,而是直接執行onStart()方法,具體的可以看下面的實例。
Service與Activity通信:
Service後端的數據最終還是要呈現在前端Activity之上的,因爲啓動Service時,系統會重新開啓一個新的進程,這就涉及到不同進程間通信的問題了(AIDL)這一節我不作過多描述,當我們想獲取啓動的Service實例時,我們可以用到bindService和onBindService方法,它們分別執行了Service中IBinder()和onUnbind()方法。
這裏要提及一點:繼承service的子類在重寫service的方法中,除了一個onStart()方法之外,還有一個onStartCommand()方法,有關onStartCommand()方法稍微作點介紹:
Android開發的過程中,每次調用startService(Intent)的時候,都會調用該Service對象的onStartCommand(Intent,int,int)方法,然後在onStartCommand方法中做一些處理。然後我們注意到這個函數有一個int的返回值,這篇文章就是簡單地講講int返回值的作用。
從Android官方文檔中,我們知道onStartCommand有4種返回值:
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 類我們如何啓動他呢,有兩種方法:
• Context.startService()
• Context.bindService()
1. 在同一個應用任何地方調用 startService() 方法就能啓動 Service 了,然後系統會回調 Service 類的 onCreate() 以及 onStart() 方法。這樣啓動的 Service 會一直運行在後臺,直到 Context.stopService() 或者 selfStop() 方法被調用。另外如果一個 Service 已經被啓動,其他代碼再試圖調用 startService()
方法,是不會執行 onCreate() 的,但會重新執行一次 onStart() 。
2. 另外一種 bindService() 方法的意思是,把這個 Service 和調用 Service 的客戶類綁起來,如果調用這個客戶類被銷燬,Service 也會被銷燬。用這個方法的一個好處是,bindService() 方法執行後 Service 會回調上邊提到的 onBind() 方發,你可以從這裏返回一個實現了 IBind 接口的類,在客戶端操作這個類就能和這個服務通信了,比如得到
Service 運行的狀態或其他操作。如果 Service 還沒有運行,使用這個方法啓動 Service 就會 onCreate() 方法而不會調用 onStart()。
區別概況爲:
startService() 的調用者與服務沒有聯繫,即使調用者退出了,服務仍然運行,而bindService()
的調用者與服務綁在一起,調用者一旦退出了,服務也隨即終止掉。
這裏用一個實例(使用startService()方法來啓動)來講解一下service的聲明週期和使用方法:
首先編寫一個類繼承Service這個基類,重寫裏面的方法,然後在Activity中調用startService()和stopService()來啓動和停止服務。
運行界面:
工程目錄結構:
ExampleService.java
-
package com.service.activity;
-
-
import android.app.Service;
-
import android.content.Intent;
-
import android.os.IBinder;
-
import android.util.Log;
-
-
public class ExampleService extends Service{
-
private static final String TAG = "ExampleService";
-
-
@Override
-
public void onCreate() {
-
Log.i(TAG, "ExampleService-onCreate");
-
super.onCreate();
-
}
-
-
@Override
-
public void onStart(Intent intent, int startId) {
-
Log.i(TAG, "ExampleService-onStart");
-
super.onStart(intent, startId);
-
}
-
-
@Override
-
public int onStartCommand(Intent intent, int flags, int startId) {
-
//執行文件的下載或者播放等操作
-
Log.i(TAG, "ExampleService-onStartCommand");
-
/*
-
* 這裏返回狀態有三個值,分別是:
-
* 1、START_STICKY:當服務進程在運行時被殺死,系統將會把它置爲started狀態,但是不保存其傳遞的Intent對象,之後,系統會嘗試重新創建服務;
-
* 2、START_NOT_STICKY:當服務進程在運行時被殺死,並且沒有新的Intent對象傳遞過來的話,系統將會把它置爲started狀態,
-
* 但是系統不會重新創建服務,直到startService(Intent intent)方法再次被調用;
-
* 3、START_REDELIVER_INTENT:當服務進程在運行時被殺死,它將會在隔一段時間後自動創建,並且最後一個傳遞的Intent對象將會再次傳遞過來。
-
*/
-
return super.onStartCommand(intent, flags, startId);
-
}
-
-
@Override
-
public IBinder onBind(Intent intent) {
-
Log.i(TAG, "ExampleService-onBind");
-
return null;
-
}
-
-
@Override
-
public void onDestroy() {
-
Log.i(TAG, "ExampleService-onDestroy");
-
super.onDestroy();
-
}
-
-
}
MainActivity.java
-
package com.service.activity;
-
-
import android.app.Activity;
-
import android.content.Intent;
-
import android.os.Bundle;
-
import android.view.View;
-
import android.view.View.OnClickListener;
-
import android.widget.Button;
-
-
public class MainActivity extends Activity implements OnClickListener{
-
private static final String TAG = "MainActivity"; //日誌輸出標誌
-
private Button btnStartService;
-
private Button btnStopService;
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
btnStartService = (Button)findViewById(R.id.btnStartService);
-
btnStopService = (Button)findViewById(R.id.btnStopService);
-
btnStartService.setOnClickListener(this);
-
btnStopService.setOnClickListener(this);
-
}
-
//點擊事件處理監聽器
-
@Override
-
public void onClick(View v) {
-
Intent intent = new Intent(MainActivity.this,ExampleService.class);
-
switch(v.getId()){
-
case R.id.btnStartService:
-
startService(intent);
-
break;
-
case R.id.btnStopService:
-
stopService(intent);
-
break;
-
default:
-
break;
-
}
-
}
-
}
最後在AndroidManifest.xml中對service進行聲明,它跟Activity同一級,都寫在Application標籤裏面:
<service android:name=".ExampleService"/>
創建完運行
在運行點擊"啓動service"之後(第一次啓動service),我們可以查看LogCat控制檯輸出的日誌如下:
這個時候我們點擊"返回",Activity被幹掉了,但是我們的服務仍然在運行,可以查看Setting-->Application-->Running Service,截圖如下:
然後回到我們的Activity,再次點擊啓動Service,控制檯輸出日誌如下:
onCreate()方法沒有被調用,說明它並沒有重新被創建。
然後我們點擊停止Service,輸出日誌如下: