Android Service學習(1)——Service啓動方式之startService

1.Service概念及用途:
        A service is an application component that can perform long-running operations in the background and does not provide a user interface。
       通常service用來執行一些耗時操作,或者後臺執行不提供用戶交互界面的操作,例如:下載、播放音樂。

2.Service生命週期 :
        Android Service的生命週期並不像Activity那麼複雜,它只繼承了onCreate(),onStart(),onDestroy()三個方法,當我們第一次啓動Service時,先後調用了onCreate(),onStart()這兩個方法,當停止Service時,則執行onDestroy()方法,這裏需要注意的是,如果Service已經啓動了,當我們再次啓動Service時,不會在執行onCreate()方法,而是直接執行onStart()方法,具體的可以看下面的實例。

3.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()來啓動和停止服務

運行界面:
 
工程目錄結構:
 

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
[html] 
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,輸出日誌如下:


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