服務是實現程序後臺運行的解決方案,適合用於執行那些不需要和用戶交互且要求長期運行的任務。
服務並不是運行在一個獨立的進程當中,而是依賴於創建服務時所在的應用程序進程,當某個應用程序進程被殺掉時,所有依賴於該進程的服務也會停止運行
- 定義一個服務
創建一個類,並讓它繼承 Service,一般會重寫 onBind()、onCreate()、onStartCommand()、和 onDestroy() 這幾個方法
public class MyService extends Service{
public IBinder onBind(Intent intent){
return null;
}
public void onCreate(){
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId){
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy(){
super.onDestroy();
}
}
然後要在 AndroidManifest.xml 文件中進行註冊
<service android:name=".MyService"></service>
這樣,就將一個服務完全定義好了
onCreate() 方法是在服務第一次創建的時候調用的
onStartCommand() 方法則在每次啓動服務的時候都會調用
- 啓動和停止服務
在佈局中添加兩個按鈕用來實現啓動服務和停止服務的功能
public class MainActivity extends Activity implements OnClickListener{
private Button startService;
private Button stopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
startService = (Button)findViewById(R.id.start_service);
stopService = (Button)findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.start_service:
// 啓動服務
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
// 停止服務
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
default:
break;
}
}
}
- 活動和服務進行通信
主要要利用 Binder
實例:服務裏提供一個下載功能,然後在活動中可以決定何時開始下載,以及隨時查看下載進度
新建一個 DownloadBinder 類,並繼承自 Binder,然後在它內部提供了開始下載和查看進度的方法,接着在 MyService 中創建 DownloadBinder 的實例,然後在 onBind() 方法裏返回這個實例
public class MyService extends Service{
// 創建 Binder 的實例
private DownloadBinder mBinder = new DownloadBinder();
/*
* 新建一個類繼承 Binder
*/
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
public IBinder onBind(Intent intent){
// 返回 Binder 的實例
return mBinder;
}
public void onCreate(){
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId){
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy(){
super.onDestroy();
}
}
在佈局中添加兩個按鈕用來實現綁定服務和取消綁定服務,修改 MainActivity 中的代碼
public class MainActivity extends Activity implements OnClickListener{
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.DownloadBinder downloadBinder;
// 創建一個 ServiceConnection 的匿名類
private ServiceConnection connection = new ServiceConnection(){
// 活動與服務解除綁定時被調用
public void onServiceDisconnected(ComponentName name){
}
// 活動與服務綁定成功時被調用
public void onServiceConnected(ComponentName name, IBinder service){
// 向下轉型,獲取 DownloadBinder 的實例
downloadBinder = (MyService.DownloadBinder)service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
startService = (Button)findViewById(R.id.start_service);
stopService = (Button)findViewById(R.id.stop_service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService = (Button)findViewById(R.id.bind_service);
bindService.setOnClickListener(this);
unbindService = (Button)findViewById(R.id.unbind_service);
unbindService.setOnClickListener(this);
}
public void onClick(View v){
switch(v.getId()){
case R.id.start_service:
// 啓動服務
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
// 停止服務
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
case R.id.bind_service:
// 綁定服務
Intent bindIntent = new Intent(this, MyService.class);
/*
* BIND_AUTO_CREATE 表示在活動和服務進行綁定後自動創建服務
* 這會使用服務中的 onCreate() 方法得到執行
* 但 onStartCommand() 方法不會執行
*/
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
// 解綁服務
unbindService(connection);
break;
default:
break;
}
}
}
首先創建了一個 ServiceConnection 的匿名類,在裏面重寫了 onServiceConnected() 方法和 onServiceDisconnected() 方法,這兩個方法分別會在活動與服務成功以及解除綁定的時候被調用。
在 onServiceConnected() 方法中,通過向下轉型得到了 DownloadBinder 的實例,可以通過這個實例根據具體的場景調用 DownloadBinder 中的任何方法。
活動和服務的綁定通過調用 bindService() 方法,BIND_AUTO_CREATE 標誌表示在活動和服務進行綁定後自動創建服務,這會使得服務中的 onCreate() 方法得到執行,但 onStartCommand() 方法不會執行。
- 服務的生命週期
- 調用 startService() 方法,相應的服務就會啓動起來,並回調 onStartCommand() 方法。如果這個服務之前還沒有創建過,onCreate() 方法會先於 onStartCommand() 方法執行。服務啓動了之後會一直保持運行狀態,直到 stopService() 或 stopSelf() 方法被調用。雖然每調用一次 startService() 方法,onStartCommand() 就會執行一次,但實際上每個服務都只會存在一個實例。所以不管調用了多少次 startService() 方法,只需調用一次 stopService() 或 stopSelf(),服務就會停止下來。
- 通過調用 bindService() 方法可以獲取一個服務的持久連接,這時會回調服務中的 onBind() 方法。類似地,如果這個服務之前還沒有創建過,onCreate() 方法會先於 onBind() 方法執行。之後,調用方可以獲取到 onBind() 方法裏返回的 IBinder 對象的實例,這樣就能自由地和服務進行通信。
- 當調用了 startService() 方法後,又去調用 stopService() 方法,這時服務中的 onDestroy() 方法就會執行,表示服務已經銷燬。類似 bindService() 方法和 unbindService() 方法組合。如果一個服務既調用了 startService() 方法,又調用了 bindService() 方法,這種情況要同時調用 stopService() 和 unbindService() 方法,onDestroy() 方法纔會執行。