android service教程

原文地址:http://www.javacodegeeks.com/2014/01/android-service-tutorial.html

在這篇博文中,我們想討論Android Service。在開發Android app時這是一個重要的組件。跟Activity不同的是,Android中的Service運行在後臺,它們沒有接口和不同於Activity的生命週期。使用Service我們能實現一些後臺操作,例如,我們能支持我們想從一個遠程服務器載入一個web頁面。在Android中使用Service我們能實現多任務。


Service綜述


我們已經知道,如果系統資源變的太低,Android Activity能被開始,停止,銷燬和重建,一個Service被設計成有一個更長的生命週期。Android中的一個Service能從一個Activity開始,從一個Broadcast接收,還可以從其它service開始。


我們必須注意到使用Service我們不是自動的創建一個新的線程,因此如果我們在service裏實現一個不需要太長時間處理的簡單的邏輯,我們不需要在分開的線程中運行它,但是如果我們必須實現使用長時間的複雜的邏輯,我們必須考慮創建一個新線程,否則這個service運行在主線程有可能會導致ANR問題。


在Android中有兩個原因適用Service:

實現多任務

開啓內部處理通信


第一個案例的一個典型的例子是一個app從一個遠程服務器下載輸入,在這個案例中我們使Activity跟一個用戶交互並且當用戶適用這個app的時候開啓一個service在後臺完成工作,也許當service完成的時候會給用戶發送一個消息。


在第二個案例中,我們想“共享”一些共有的方法以至於不同的app能重複利用它們。例如,我們能支持我們是service發送一個郵件並且我們想在幾個app之間不需要重寫代碼就可以共享這個service。在這個案例中我們能使用IPC爲的是service暴露一個“遠程”接口能被其它app調用。


在這篇文章中,我們包含了第一個例子,在這個例子中我們有一個本地service,本地意味着這個service僅僅能在我們的apk中可見。


Service基礎


現在關於Service我們知道了更多,我們想創建它。在Android中,我們想要創建一個Service就必須繼承Service類。


public class TestService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}


正如我們看到的,我們必須實現叫做onBind的唯一的一個方法。在我們的例子中,我們使用本地service,因此這個方法應該返回null。在我們提及以前,一個Service有它的生命週期並且我們能覆蓋一些回調方法來持有它的不同狀態。


public class TestService extends Service {

    @Override
    public void onCreate() {        
        super.onCreate();
    }

    @Override
    public void onDestroy() {        
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {        
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}


當Service已經被創建的時候,第一個方法onCreate被調用僅僅一次。如果這個Service已經在運行這個方法,那它就不會被調用。我們不會直接調用它,但是它是OS調用的。


onStartCommand是最重要的方法因爲當我們請求啓動Service時它被調用。在這個方法中我們讓Intent傳遞我們運行的Service,用這種方式,我們能用Service改變一些信息。在這個方法中,我們實現了在這個方法中能直接執行的我們的邏輯,如果它的時間不是昂貴的,否則我們能創建一個線程。正如你看到的這個方法要求我們返回一個整型結果。這個整數代表着這個Service應當被OS如何持有:


START_STICKY:使用返回值,如果OS殺掉我們的Service,它將重新創建它,但是被髮送到Service中的Intent不是可傳遞的。用這種方式Service總是在運行中。

START_NOT_STICKY:如果OS殺掉Service,它將不重新創建它,直到客戶端顯示調用onStart命令

START_REDELIVER_INTENT:它與START_STICKY是相似的,並且在這個例子中,Intent將被重新傳遞到Service中。


當Service被銷燬的時候,OnDestroy是被OS調用的方法。


一旦我們有了我們的Service類,爲了我們能用它,我們必須在Manifest.xml中定義它。

<service android:name=".TestService" 
         android:enabled="true"/>


開始和停止Service


正如我們瞭解的,一個Service爲了完成它的任務,必須被啓動並且完全的被停止。我們能猜想它從一個activity開始,並且我們使用Intent能給service傳遞一些信息。我們假設我們的Activity有兩個按鈕,一個是開始,一個是停止Service:

btnStart.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        i.putExtra("name", "SurvivingwithAndroid");        
        MainActivity.this.startService(i);        
    }
});

btnStop.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        MainActivity.this.stopService(i);
    }
});


在上面的第5行,我們創建了一個持有我們的Service的Intent傳遞類名,而且我們設置一些參數像名字,然後我們在第7行開啓Service。用相同的方式,在17行我們停止service。

在start按鈕上點擊我們得到下面的日誌:



因爲我們是第一次開啓service,因此我們注意到onCreate方法被調用,如果我們再在start按鈕上點擊,OS不會調用onCreate方法。當我們在stop按鈕上點擊時,OS銷燬service。


IntentService


正如我們提到的,在主線程上,一個service運行以前,我們在這個service中當我們實現一些邏輯時我們必須小心。我們必須考慮是否這個邏輯是一個阻塞操作或者它要求很長時間去完成導致可能出現一個ANR問題。在這個案例中我們必須把我們的邏輯移到分隔的線程中,意味着我們必須在onStartCommand方法中創建一個線程並且運行它。


有另一個由Service衍生而來的叫做IntentService的類簡化了我們的工作。當我們在同一時間不需要持有多個請求時這個類是有用的。這個類創建一個工作線程來持有不同的請求。這個類執行這些操作:


創建一個分隔線程持有這個請求

創建一個請求隊列並且同時傳遞一個Intent

創建一個默認的onStartCommand實現

當所有的請求被處理了,停止service


如果我們想創建一個IntentService我們必須繼承IntentService類代替Service:

public class TestIntentService extends IntentService {

    public TestIntentService() {
        super("TestIntentService");        
    }

    @Override
    protected void onHandleIntent(Intent intent) {

    }

}


在這個案例中我們僅僅實現一個叫做onHandleIntent的方法。在這裏我們實現輸出邏輯,不關心操作是否需要很長時間,因爲這個方法在另一個線程中被調用。


自動開啓service


很多時候我們想讓service自動啓動,例如在引導時。我們知道開啓一個service我們需要一個開啓它的組件。我們該怎麼做呢?我們可以使用一個Broadcast接收器開啓我們的service。如果按照例子我們想在手機啓動時開啓它,我們首先要創建一個Broadcast接收器堅挺事件並且然後開啓service。

public class BootBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context ctx, Intent intent) {        
        ctx.startService(new Intent(ctx, TestService.class));

    }

}


並且在Manifest.xml中:

<receiver android:name=".BootBroadcast">    
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED"/>                
    </intent-filter>
</receiver>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章