![]() |
[Android SDK特色教學] Service服務的原理及使用 |
Service是android系統中的四大組件之一。與一般充斥著各種UI元件的Activity最大區別就是「服務Service完全沒有UI」,Android系統中服務(Service)是在背景執行的東西,就類似定時或週期性的任務。假設你可以利用一個Activity去啟動一個服務(Service)來播放音樂;或者定時記錄你地理訊息位置(GPS)的改變;或者需要下載網路資料時,都可以好好利用服務來幫助你達成任務。Service的啟動有兩種方式:context.startService() 和 context.bindService()。
Android Service的生命週期並不像Activity那麼複雜,它只繼承其中的onCreate()、onStart()、onDestroy()三種方法而已,當我們第一次啟動Service時,先後呼叫了onCreate()、onStartCommand()這兩個方法,需要特別注意的是Android 2.0版之前是呼叫onStart();但是在android 2.0之後已經改成呼叫onStartCommand()了!當停止Service時,則執行onDestroy()方法,這裡需要注意的是,如果Service已經啟動了,當我們再次啟動Service時,不會在執行onCreate()方法,而是直接執行onStartCommand()方法。
使用執行緒還是服務?
即使使用者沒和應用程式互動,服務仍然可以在背景執行。因此,你應該在需要時才使用它「Service」。如果你不想在主執行緒另外執行一個任務,而是僅當使用者和應用互動時執行該任務,你應該建立新執行緒而不是服務。例如,你只想activity執行時才播放音樂,就可以在onCreate()方法裡建立一個執行緒,在onStart()方法裡啟動該執行緒,在onStop()方法裡關閉它。也可以考慮用AsyncTask或者HandlerThread,代替傳統的Thread類別。記住如果你使用了一個服務,它仍然會在主執行緒裡執行,所以,遇到耗時或非同步操作,可以建立一個新執行緒,然後再啟動該服務。
可透過底下兩種方式來開啟Service:
- context.startService()
- context.bindService()
context.startService()啟動服務流程:
- 直接呼叫Context內的startService()表示已明確開啟Service
- 系統開啟Service後會自動呼叫該Service的onCreate()
- 再來呼叫該Service的onStartCommand()
- 如果呼叫Context的stopService(),會終止該Service;此時系統會呼叫該Service的onDestroy()並且關閉該Service
context.startService()一旦啟動,服務就直接在背景無限執行,即使啟動它的Activity被銷毀。通常startService()服務啟動後並不返回結果給使用者。例如,它會通過網絡下載、上傳文件,當一個任務執行完成,就會等著讓其他組件通過呼叫stopService()方法停止該服務,Android系統並不會自動銷毀該服務。
- 一定要extends Service
- 一定要Override onBind()方法,不過現在用不到,return值可以設為null
- 一定要在AndroidManifest.xml註冊
<service android:name=".ExampleService"></service>MyService類別程式碼:
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private Handler handler = new Handler();
private Runnable showTime = new Runnable() {
public void run() {
// log目前時間
Log.i("time:", new Date().toString());
handler.postDelayed(this, 1000);
}
};
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.i("服務", "建立");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i("服務", "銷毀");
handler.removeCallbacks(showTime);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.i("服務", "執行");
handler.postDelayed(showTime, 1000);
return super.onStartCommand(intent, flags, startId);
}
}
MainActivity類別程式碼:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ToggleButton;
public class MainActivity extends Activity {
ToggleButton tbu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tbu = (ToggleButton) findViewById(R.id.toggleButton1);
tbu.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (buttonView == tbu && isChecked == true) {
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
}
if (buttonView == tbu && isChecked == false) {
Intent intent = new Intent(MainActivity.this,MyService.class);
stopService(intent);
}
}
});
}
}
context.bindService()啟動服務流程:
- 呼叫Context的bindService()會連結Service,若Service未開啟就會自動開啟。
- 開啟Service後會呼叫onCreate()但是不會呼叫onStartCommand()
- 呼叫onBind()並傳回IBinder物件
- 呼叫ServiceConnection類別中的onServiceConnected()方法,並將步驟3的IBinder物件當作參數傳遞給onServiceConnected(),透過IBinder可以取得跟Service的聯繫。例如直接呼叫該Service內的公用方法。
- 呼叫Context的unbindService()方法,則系統會呼叫該Service的onUnbind()以解除Context與Service的聯繫;隨後會自動呼叫Service的onDestroy()銷毀服務。
context.bindService()運用來綁定服務提供使用者允許Activity與Sevice互動;發送請求;獲得結果,甚至多行程互相執行這些操作。服務和另一個與之綁定的組件執行時間一樣長;若有多個組件也只能和同一個服務綁定一次。但所有組件取消綁定之後,服務就會自動銷毀。(這點跟context.startService()很不一樣!)但其實服務可以同時用以上兩種方式工作:startService()、bindService(),所以可以啟動之後無限期執行而且允許綁定Activity。這只取決你有沒有實現這兩種服務的回調介面: 「onBind()」。
MyService類別程式碼:
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
public class ServiceBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
private final IBinder mBinder = new ServiceBinder();
private Handler handler = new Handler();
private Runnable showTime = new Runnable() {
public void run() {
// log目前時間
Log.i("time:", new Date().toString());
handler.postDelayed(this, 1000);
}
};
public void custom()
{
handler.postDelayed(showTime, 1000);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.i("服務", "呼叫onStartCommand方法");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Log.i("服務", "呼叫onBind方法");
return mBinder;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.i("服務", "建立");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i("服務", "銷毀");
handler.removeCallbacks(showTime);
}
}
MainActivity類別程式碼:
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button open,stop;
MyService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
open = (Button) findViewById(R.id.button1);
open.setOnClickListener(new OnClickListener () {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, MyService.class);
bindService(intent, connc, Context.BIND_AUTO_CREATE);
}});
stop = (Button) findViewById(R.id.button2);
stop.setOnClickListener(new OnClickListener () {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
unbindService(connc);
}});
}
private ServiceConnection connc = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myService=((MyService.ServiceBinder)service).getService();
myService.custom();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
myService=null;
}
};
}
![[Android SDK特色教學] Service服務的原理及使用 [Android SDK特色教學] Service服務的原理及使用](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihM4o-vauSYjst2F9WsZo6e0aNStKrsZ-hNzBtH26t0t51B6QJWE87Psm22SbPGvKlhgrFRKGvCjmUo1K1XEL_PBvfyb2JZBk5hq2Kjzkd0YfBIwZPvyPlew9c28kC2eCMaKGMg308VLI/s1600/33.jpg)


沒有留言 :
張貼留言