Service 本身就是處於背景中執行的 Context, 與在前景執行的 Context 不一樣. 前景是負責處理 UI/UX, 而背景中執行的任務, 通常是與 UI/UX 無關的項目, 這樣一來, 就不會影響到使用者的使用體驗, 也能同步在運作在背景中.
啟動型的 Service, 就是可以被 Context 物件實體, 以 startService() 的方式啟動 Service 物件的生命週期. 換言之, 可以由前景的 Activity, 或是另一個已經在背景執行的 Service 物件實體來啟動的 Service.
一但開始執行的 Service 物件實體及其生命週期的表現, 並不會因為啟動的 Activity 的生命週期改變而有所影響. 例如: 當啟動 Service 的 Activity 生命週期結束, 並不會導致 Service 也結束生命週期.
啟動機制模式的Service, 是藉由Context.startService()所啟動起來的Service, 啟動之後的生命週期進入到初始化處理的onCreate()及onStartCommand(). 之後的模式都是透過Context.startService()來觸發onStartCommand()來進行互動機制. 即使Context已經結束生命週期, Service仍然會繼續運作, 除非Context.stopService()被呼叫, 才會觸發onDestroy()來結束Service.
public class MyService2 extends Service {
public MyService2() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
開始要處理一下這段程式碼, 因為其預設的模式是Bound Service.
public class MyService2 extends Service {
public MyService2() {
Log.i("brad", "MyService2()");
}
@Override
public IBinder onBind(Intent intent) {
Log.i("brad", "MyService2:onBind()");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i("brad", "MyService2:onCreate()");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("brad", "MyService2:onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("brad", "MyService2:onDestroy()");
}
}
public void test2(View view){
Intent intent = new Intent(this, MyService2.class);
startService(intent);
}
public void test3(View view){
Intent intent = new Intent(this, MyService2.class);
stopService(intent);
}
透過LogCat可以清楚的觀察到:
public void test2(View view){
Intent intent = new Intent(this, MyService2.class);
intent.putExtra("username", "brad");
startService(intent);
}
而在MyService2中:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("brad", "MyService2:onStartCommand()");
String username = intent.getStringExtra("username");
return super.onStartCommand(intent, flags, startId);
}
當Activity執行階段要對Service觸發方法時, 則只需要直接對屬性中的Service物件實體操作即可.
public void doSomething(){
Log.i("brad", "doSomething...");
}
而在MainActivity中:
public void test1(View view){
mService.doSomething();
}
反過來, 要從MyService2發出資料給MainActivity, 則可以透過BroadcastReceiver的機制來處理.
public void doSomething(){
Log.i("brad", "doSomething...");
Intent intent = new Intent("brad");
intent.putExtra("rand", (int)(Math.random()*49+1));
sendBroadcast(intent);
}
回到MainActivity中, 先定義一個自訂內部類別, 繼承自BroadcastReceiver類別, 並Override其onReceive()方法.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ...
myReceiver = new MyReceiver();
filter = new IntentFilter();
filter.addAction("brad");
// ...
}
//...
private class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("brad", "receive from MyService1");
int rand = intent.getIntExtra("rand", -1);
mesg.setText("" + rand);
}
}
而分別在onStart()及onStop()進行註冊/解除.
@Override
protected void onStart() {
super.onStart();
registerReceiver(myReceiver, filter);
}
@Override
protected void onStop() {
super.onPause();
unregisterReceiver(myReceiver);
}