Android 回顧Service之Service基礎使用

來源:互聯網
上載者:User

Android 回顧Service之Service基礎使用

這兩天在回顧Android Service方面的知識,趁著記憶沒有消退之前,來總結一下。本文主要講解Service的基本概念與使用、跨進程調用Service、系統常見Service的使用。所以本文的難度微乎其微,僅適用於想回顧Service知識點的同學,或者還不怎麼瞭解Service的同學,至於Service源碼之類的東東,等老夫分析研究之後再來分享。

一、Service基礎
我相信只要接觸過Android開發的人,都或多或少的瞭解過Service。Service是什麼呢?Service是Android四大組件中與Activity最相似的組件,它完全具有自己的生命週期,不過它可沒有和Activity一樣的華麗外表,它常年在後台默默付出。Service也是可執行檔程式,前面說了它有自己的生命週期,其建立於配置過程與Activity極其相似。不僅如此,Activity與Service還有共同的父親Context,因此它們都可以調用Context裡定義的如getResources()、getContentResolver()等方法。

1、Service的簡單使用:
開發Service需要兩個步驟:(1)定義一個繼承Service的子類。(2)在AndroidManifest.xml檔案中配置該Service。

在動手開發第一個Service之前,我們先來瞭解一下Service的系列生命週期方法:
(1)IBinder onBind(Intent intent):該方法是Service子類必須實現的方法。該方法返回一個IBinder對象,應用程式可通過該對象與Service組件通訊。

(2)void onCreate():當該Service第一次被建立後將立即回調該方法。

(3)void onDestroy():當該Service被關閉之前將會回調該方法。

(4)void onStartCommand(Intent intent,int flags,int startId):該方法的早期版本是void onStart(Intent intent,int startId),每次用戶端調用startService(Intent)方法啟動該Service 時都會回調該方法。

(5)boolean onUnbind(Intent intent):當該Service上綁定的所有用戶端都中斷連線時將會回調該方法。

下面我們來開發我們的第一個Service,代碼如下:

package com.gc.servicetest;import android.app.Notification;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;/** * 注意: onCreate()方法只會在Service第一次被建立的時候調用,如果當前Service已經被建立過了, * 不管怎樣調用startService方法,onCreate()方法都不會再執行。 * @author Android將軍 * */public class MyService extends Service{public static final String TAG=MyService.class.getSimpleName();//必須要實現的方法@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.v(TAG, onBind() executed);return null;}      //Service被建立時回調該方法@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();Log.v(TAG, onCreate() executed);Log.v(TAG, MyService thread id is +Thread.currentThread().getId());            }       //Service被啟動時回調該方法@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.v(TAG, onStartCommand() executed);return super.onStartCommand(intent, flags, startId);}       //Service被關閉之前回調該方法@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();Log.v(TAG, onDestroy() executed);}}

上面這個Service什麼也沒幹——它只是重寫了Service組件的onCreate()、onStartCommand()、onDestroy()、onBind()等方法。如果希望Service組件做某些事情,那麼只要在onCreate()或onStartCommand()方法中定義相關業務代碼即可。開發Service的兩個步驟,我們現在已經走完了第一個步驟,下面我們一起走第二步吧。第二步很簡單,在AndroidManifest.xml配置Service與在該檔案中配置Activity是一樣的,只不過標籤一個是,一個是。下面給出本次的MyService的配置,代碼如下:
 

 

當兩個步驟走完,我們已經開發出了一個Service組件,接下來就可在程式中運行該Service了,Android系統中運行Service有兩種方式,如下:

(1)通過Context的startService()方法:通過該方法啟動Service,訪問者與Service之間沒有關聯,即使訪問者退出了,Service仍然運行。
(2)通過Context的bindService()方法:使用該方法啟用Service,訪問者與Service綁定在了一起,訪問者一旦退出,Service也就終止。

下面我們就來看看如何使用這兩種方式來啟動我們剛剛開發的Myservice,我們使用Activity作為Service的訪問者,該Activity的介面中包含四個按鈕,由於代碼簡單,這裡就不再給出其布局檔案,下面直接看一下MainActivity的代碼,如下

package com.gc.servicetest;import com.gc.servicetest.MyService.MyBinder;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;/** *  * @author Android將軍 * */public class MainActivity extends Activity implements OnClickListener {    public static final String TAG=MainActivity.class.getSimpleName();    private Button mBtnStartService;    private Button mBtnStopService;    private Button mBtnBindService;    private Button mBtnUnBindService;    private MyService.MyBinder myBinder;        private ServiceConnection connection=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stubLog.v(TAG, onServiceDisconnected() executed);Log.v(TAG, onServiceDisconnected() executed name+name);}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stubLog.v(TAG, onServiceConnected() executed);Log.v(TAG, onServiceConnected() executed name+name);myBinder=(MyBinder) service;myBinder.startDownload();}};@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initUI();        setListener();        Log.v(TAG, MainActivity thread id is +Thread.currentThread().getId());    }public void initUI(){mBtnStartService=(Button) findViewById(R.id.start_service);mBtnStopService=(Button) findViewById(R.id.stop_service);mBtnBindService=(Button) findViewById(R.id.bind_service);mBtnUnBindService=(Button) findViewById(R.id.unbind_service);}public void setListener(){mBtnStartService.setOnClickListener(this);mBtnStopService.setOnClickListener(this);mBtnBindService.setOnClickListener(this);mBtnUnBindService.setOnClickListener(this);}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.start_service:Intent mStartIntent=new Intent(this, MyService.class);startService(mStartIntent);break;case R.id.stop_service:Intent mStopIntent=new Intent(this, MyService.class);stopService(mStopIntent);break;case R.id.bind_service:Intent mBindIntent=new Intent(this, MyService.class);bindService(mBindIntent, connection, BIND_AUTO_CREATE);break;case R.id.unbind_service:unbindService(connection);break;default:break;}}}
到此為止,我們已經寫好了一個帶有Service功能的程式。然後我們運行程式,點擊Start Service按鈕,然後點擊Stop Service按鈕,可以看到如下列印結果:

如果在不關閉Service的情況下,連續點擊三次Start Sevice 按鈕,程式將會連續三次啟動Service,列印資訊如下:
 

從上述兩種不同的操作以及列印資訊,我們驗證了前面MyService注釋部分注意的內容的正確性,如下:

onCreate()方法只會在Service第一次被建立的時候調用,如果當前Service已經被建立過了, 不管怎樣調用startService方法,onCreate()方法都不會再執行。

現在我們已經瞭解了第一種方式,那麼我接下來看看第二種方式:
在第一種方式中,MyService與MainActivity之間基本上不存在太多的關聯,因此MyService與MainActivity之間無法進行通訊、資料交換。如果想讓MyService和MainActivity之間進行方法調用或資料交換,則應該採用第二種方式啟動MyService,即使用bindService()和unbindService()方法啟動、關閉Service。在使用第二種方式啟動MyService之前,肯定是要修改前面MyService的代碼的,修改之後的代碼如下:

public class MyService extends Service{public static final String TAG=MyService.class.getSimpleName();private MyBinder mBinder=new MyBinder();@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.v(TAG, onBind() executed);return mBinder;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();Log.v(TAG, onCreate() executed);Log.v(TAG, MyService thread id is +Thread.currentThread().getId());       }@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.v(TAG, onStartCommand() executed);return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();Log.v(TAG, onDestroy() executed);}class MyBinder extends Binder{public void startDownload(){Log.v(TAG, startDownload() executed);}}}
在進行操作之前,我們先瞭解一下bindService方法:
Context的bindService()方法的源碼如下:
 public boolean bindService(Intent service, ServiceConnection conn,            int flags) {        return mBase.bindService(service, conn, flags);    }
這裡解釋一下該方法的三個參數:
service:該參數通過Intent指定要啟動的Service。

conn:該參數是一個ServiceConnection對象,該對象用於監聽訪問者與Service之間的串連情況。當訪問者與Service之間串連成功時將回調該ServiceConnecttion對象的onServiceConnected(ComponentName name,IBinder service)方法;當Service所在的宿主進程由於異常終止或由於其他原因終止,導致該Service與訪問者之間中斷連線時回調該ServiceConnection對象的onServiceDisconnected(ComponentName name)方法。

注意:當調用者主動通過unBindService()方法斷開與Service的串連時,ServiceConnection對象的onServiceDisconnected(ComponentName name)方法並不會被調用。

flags:指定綁定時是否自動建立Service(如果Service還未建立)。該參數可指定為0(不自動建立)或BIND_AUTO_CREATE(自動建立)。

注意到ServiceConnection對象的onServiceConnected方法中有一個IBinder對象,該對象即可實現與被綁定Service之間的通訊。

額,囉嗦了這麼多,是不是有點暈了,咱們看看第二種方式啟動MyService的執行效果吧,運行程式,點擊Bind Service,然後點擊unBind Service,列印資訊如下:

通過我們可以看到,MainActivity已經成功的和MyService進行了通訊。我們在MainActivity的成員對象connection的onServiceConnected的方法中調用了startDownload()方法。

下面我們來總結一下:

開發Service需要兩個步驟:(1)定義一個繼承Service的子類。(2)在AndroidManifest.xml檔案中配置該Service。

啟動Service有兩種方式:(1)startService方法(2)bindService方法

通過startService方式啟動Service,Service與訪問者之間的基本上沒有太大的關聯。通過bindService方式啟動Service,可以實現Service與訪問者之間的通訊。那麼當通過bindService啟動Service時,是如何進行通訊的呢?我們按照本案例分析一下,當我們開發MyService類時,我們必須實現的方法是IBinder onBinder(Intent intent),當我們通過bindService方法啟動MyService時,我們已經把MainActivity與MyService綁定在一起了,這時MyService方法的onBind方法所返回的IBinder對象將會傳給MainActivity的成員connection裡的onServiceConnected(ComponentName name,IBinder service)方法的service參數,這樣MainActivity就可通過該IBinder對象與MyService進行通訊了。

細心的通訊會發現,通過startService啟動Service時,調用了onStartCommand方法,而通過bindService方法啟動Service時,並沒有調用onStartCommand方法,這是為什呢?這是因為兩種方式啟動Service,導致Service的生命週期略有不同。在下一篇的Service的生命週期中,我會講述清楚。

好了,BB了這麼多,我想對於Service的基礎知識應該差不多了,我會在文章末尾提供該Demo的,如果對你有協助可以稍微頂一下奧,如果文中有哪裡不正確,歡迎指出,如果還有疑問之處,或者我沒有闡述清楚的地方,請留言指出,謝謝。

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.