Android組件——服務

服務是實現程序後臺運行的解決方案,適合用於執行那些不需要和用戶交互且要求長期運行的任務。

服務並不是運行在一個獨立的進程當中,而是依賴於創建服務時所在的應用程序進程,當某個應用程序進程被殺掉時,所有依賴於該進程的服務也會停止運行

  • 定義一個服務

創建一個類,並讓它繼承 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() 方法不會執行。


  • 服務的生命週期
  1. 調用 startService() 方法,相應的服務就會啓動起來,並回調 onStartCommand() 方法。如果這個服務之前還沒有創建過,onCreate() 方法會先於 onStartCommand() 方法執行。服務啓動了之後會一直保持運行狀態,直到 stopService() 或 stopSelf() 方法被調用。雖然每調用一次 startService() 方法,onStartCommand() 就會執行一次,但實際上每個服務都只會存在一個實例。所以不管調用了多少次 startService() 方法,只需調用一次 stopService() 或 stopSelf(),服務就會停止下來。
  2. 通過調用 bindService() 方法可以獲取一個服務的持久連接,這時會回調服務中的 onBind() 方法。類似地,如果這個服務之前還沒有創建過,onCreate() 方法會先於 onBind() 方法執行。之後,調用方可以獲取到 onBind() 方法裏返回的 IBinder 對象的實例,這樣就能自由地和服務進行通信。
  3. 當調用了 startService() 方法後,又去調用 stopService() 方法,這時服務中的 onDestroy() 方法就會執行,表示服務已經銷燬。類似 bindService() 方法和 unbindService() 方法組合。如果一個服務既調用了 startService() 方法,又調用了 bindService() 方法,這種情況要同時調用 stopService() 和 unbindService() 方法,onDestroy() 方法纔會執行。


發佈了38 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章