1. 程式人生 > >Android Service 服務 三 bindService與remoteService

Android Service 服務 三 bindService與remoteService

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

一、bindService簡介

bindService是繫結Service服務,執行service服務中的邏輯流程。

service通過Context.startService()方法開始,通過Context.stopService()方法停止;也可以通過Service.stopSelf()方法或者Service.stopSelfResult()方法來停止自己。只要呼叫一次stopService()方法便可以停止服務,無論之前它被呼叫了多少次的啟動服務方法。

 

客戶端建立一個與Service的連線,並使用此連線與Service進行通話,通過Context.bindService()方法來繫結服務,Context.unbindService()方法來關閉服務。多個客戶端可以繫結同一個服務,如果Service還未被啟動,bindService()方法可以啟動服務。

 

上面startService()和bindService()兩種模式是完全獨立的。你可以繫結一個已經通過startService()方法啟動的服務。例如:一個後臺播放音樂服務可以通過startService(intend)物件來播放音樂。可能使用者在播放過程中要執行一些操作比如獲取歌曲的一些資訊,此時activity可以通過呼叫bindServices()方法與Service建立連線。這種情況下,stopServices()方法實際上不會停止服務,直到最後一次繫結關閉。


二、bindService啟動流程

context.bindService()  ——> onCreate()  ——onBind()  ——> Service running  ——onUnbind()  ——onDestroy()  ——Service stop
 

onBind()將返回給客戶端一個IBind介面例項,IBind允許客戶端回撥服務的方法,比如得到Service的例項、執行狀態或其他操作。這個時候把呼叫者(Context,例如Activity)會和Service繫結在一起,Context退出了,Srevice就會呼叫onUnbind->onDestroy相應退出。 

所以呼叫bindService的生命週期為:onCreate --> onBind(只一次,不可多次繫結) --> onUnbind --> onDestory。

在Service每一次的開啟關閉過程中,只有onStart可被多次呼叫(通過多次startService呼叫),其他onCreate,onBind,onUnbind,onDestory在一個生命週期中只能被呼叫一次。詳見:Android Service 服務(一)—— Service


三、bindService生命週期

像一個activity那樣,一個service有些可以用來改變狀態的生命週期方法,但是比activity的方法少,service生命週期方法只有三個public

   void onCreate()

   void onStart(Intent intent)

   void onDestroy()

通過實現這三個生命週期方法,你可以監聽service的兩個巢狀迴圈的生命週期:

1、整個生命週期

 service的整個生命週期是在onCreate()和onDestroy()方法之間。和activity一樣,在onCreate()方法裡初始化,在onDestroy()方法裡釋放資源。例如,一個背景音樂播放服務可以在onCreate()方法裡播放,在onDestroy()方法裡停止。

 

2、活動的生命週期

 service的活動生命週期是在onStart()之後,這個方法會處理通過startServices()方法傳遞來的Intent物件。音樂service可以通過開打intent物件來找到要播放的音樂,然後開始後臺播放。注: service停止時沒有相應的回撥方法,即沒有onStop()方法,只有onDestroy()銷燬方法。

 

onCreate()方法和onDestroy()方法是針對所有的services,無論它們是否啟動,通過Context.startService()和Context.bindService()方法都可以訪問執行。然而,只有通過startService()方法啟動service服務時才會呼叫onStart()方法

 

如果一個service允許別人繫結,那麼需要實現以下額外的方法:

       IBinder onBind(Intent intent)

       boolean onUnbind(Intent intent)

       void onRebind(Intent intent)

onBind()回撥方法會繼續傳遞通過bindService()傳遞來的intent物件

onUnbind()會處理傳遞給unbindService()的intent物件。如果service允許繫結,onBind()會返回客戶端與服務互相聯絡的通訊控制代碼(例項)。

如果建立了一個新的客戶端與服務的連線,onUnbind()方法可以請求呼叫onRebind()方法。


記住: 任何服務無論它怎樣建立,預設客戶端都可以連線,所以任何service都能夠接收onBind()和onUnbind()方法



四、bindService示例

Activity

public class PlayBindMusic extends Activity implements OnClickListener private Button playBtn; private Button stopBtn; private Button pauseBtn; private Button exitBtn; private BindMusicService musicService; @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.bind_music_service);  playBtn = (Button) findViewById(R.id.play);  stopBtn = (Button) findViewById(R.id.stop);  pauseBtn = (Button) findViewById(R.id.pause);  exitBtn = (Button) findViewById(R.id.exit);  playBtn.setOnClickListener(this);  stopBtn.setOnClickListener(this);  pauseBtn.setOnClickListener(this);  exitBtn.setOnClickListener(this);  connection(); } private void connection() {  Intent intent = new Intent("com.homer.bind.bindService");  bindService(intent, sc, Context.BIND_AUTO_CREATE);   // bindService } @Override public void onClick(View v) {  switch (v.getId()) {  case R.id.play:   musicService.play();   break;  case R.id.stop:   if (musicService != null) {    musicService.stop();   }   break;  case R.id.pause:   if (musicService != null) {    musicService.pause();   }   break;  case R.id.exit:   this.finish();   break;  } } private ServiceConnection sc = new ServiceConnection() {  @Override  public void onServiceConnected(ComponentName name, IBinder service) {  //connect Service   musicService = ((BindMusicService.MyBinder) (service)).getService();   if (musicService != null) {    musicService.play();  // play music   }  }    @Override  public void onServiceDisconnected(ComponentName name) {     //disconnect Service   musicService = null;  } };  @Override public void onDestroy(){  super.onDestroy();    if(sc != null){   unbindService(sc);  } }}

Service

public class BindMusicService extends Service private MediaPlayer mediaPlayer; private final IBinder binder = new MyBinder(); public class MyBinder extends Binder {  BindMusicService getService() {   return BindMusicService.this;  } } @Override public IBinder onBind(Intent intent) {  return binder; } @Override public void onCreate() {  super.onCreate();    Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show(); } @Override public void onDestroy() {  super.onDestroy();    Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);  if(mediaPlayer != null){   mediaPlayer.stop();   mediaPlayer.release();  } }  public void play() {  if (mediaPlayer == null) {   mediaPlayer = MediaPlayer.create(this, R.raw.tmp);   mediaPlayer.setLooping(false);  }  if (!mediaPlayer.isPlaying()) {   mediaPlayer.start();  } } public void pause() {  if (mediaPlayer != null && mediaPlayer.isPlaying()) {   mediaPlayer.pause();  } } public void stop() {  if (mediaPlayer != null) {   mediaPlayer.stop();   try {    mediaPlayer.prepare();  // 在呼叫stop後如果需要再次通過start進行播放,需要之前呼叫prepare函式   } catch (IOException ex) {    ex.printStackTrace();   }  } }}

AndroidManifest.xml

        <service            android:name=".bind.BindMusicService"            android:enabled="true" >            <intent-filter>                <action android:name="com.homer.bind.bindService" />            </intent-filter>        </service>


五、程式碼解析

1、 Activity中,Intent intent = new Intent("com.homer.bind.bindService"); 構建一個service的action,然後bindService(intent, sc, Context.BIND_AUTO_CREATE); 繫結服務

2、 Activity中,通過private ServiceConnection sc = new ServiceConnection() 建立一個Service連線,onServiceConnected()獲取Service例項,onServiceDisconnected()釋放連線

3、 Service中,過載onBind(Intent intent)方法,返回Service例項(即BindMusicService)給Activity,然後執行onCreate()函式(注:bindService不執行onStart()函式)

4、 Activity中,通過返回的Service例項musicService,執行音樂播放的操作(play、pause、stop等)



六、Remote Service拓展

通常每個應用程式都在它自己的程序內執行,但有時需要在程序之間傳遞物件(IPC通訊),你可以通過應用程式UI的方式寫個執行在一個不同的程序中的service。在android平臺中,一個程序通常不能訪問其它程序中的記憶體區域。所以,他們需要把物件拆分成作業系統能理解的簡單形式,以便偽裝成物件跨越邊界訪問。編寫這種偽裝程式碼相當的枯燥乏味,好在android為我們提供了AIDL工具可以來做這件事。
 
AIDL(android介面描述語言)是一個IDL語言,它可以生成一段程式碼,可以使在一個android裝置上執行的兩個程序使用內部通訊程序進行互動。如果你需要在一個程序中(例如在一個Activity中)訪問另一個程序中(例如一個Service)某個物件的方法,你就可以使用AIDL來生成這樣的程式碼來偽裝傳遞各種引數。
 
要使用AIDL,Service需要以aidl檔案的方式提供服務介面,AIDL工具將生成一個相應的java介面,並且在生成的服務介面中包含一個功能呼叫的stub服務樁類。Service的實現類需要去繼承這個stub服務樁類。Service的onBind方法會返回實現類的物件,之後你就可以使用它了,參見下例:

IMusicControlService.aidl

package com.homer.remote;interface IMusicControlService{        void play();         void stop();         void pause();}

使用eclipse的Android外掛,會根據這個aidl檔案生成一個Java介面類,生成的介面類中會有一個內部類Stub類,Service來繼承該Stub類: Service
public class RemoteMusicService extends Service private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent intent) {  return binder; } private final IMusicControlService.Stub binder = new IMusicControlService.Stub() {  @Override  public void play() throws RemoteException {   if (mediaPlayer == null) {    mediaPlayer = MediaPlayer.create(RemoteMusicService.this, R.raw.tmp);    mediaPlayer.setLooping(false);   }   if (!mediaPlayer.isPlaying()) {    mediaPlayer.start();   }  }  @Override  public void pause() throws RemoteException {   if (mediaPlayer != null && mediaPlayer.isPlaying()) {    mediaPlayer.pause();   }     }  @Override  public void stop() throws RemoteException {   if (mediaPlayer != null) {    mediaPlayer.stop();    try {     mediaPlayer.prepare();  // 在呼叫stop後如果需要再次通過start進行播放,需要之前呼叫prepare函式    } catch (IOException ex) {     ex.printStackTrace();    }   }  } };  @Override public void onDestroy() {  super.onDestroy();    if(mediaPlayer != null){   mediaPlayer.stop();   mediaPlayer.release();  } }}

客戶端(Activity)應用連線到這個Service時,onServiceConnected方法將被呼叫,客戶端就可以獲得IBinder物件。參看下面的客戶端onServiceConnected方法:

Activity

public class PlayRemoteMusic extends Activity implements OnClickListener private Button playBtn; private Button stopBtn; private Button pauseBtn; private Button exitBtn; private IMusicControlService musicService; @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.remote_music_service);  playBtn = (Button) findViewById(R.id.play);  stopBtn = (Button) findViewById(R.id.stop);  pauseBtn = (Button) findViewById(R.id.pause);  exitBtn = (Button) findViewById(R.id.exit);  playBtn.setOnClickListener(this);  stopBtn.setOnClickListener(this);  pauseBtn.setOnClickListener(this);  exitBtn.setOnClickListener(this);  connection(); } private void connection() {  Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");  bindService(intent, sc, Context.BIND_AUTO_CREATE);    // bindService } @Override public void onClick(View v) {  try {   switch (v.getId()) {   case R.id.play:    musicService.play();    break;   case R.id.stop:    if (musicService != null) {     musicService.stop();    }    break;   case R.id.pause:    if (musicService != null) {     musicService.pause();    }    break;   case R.id.exit:    this.finish();    break;   }  } catch (RemoteException e) {   e.printStackTrace();  } } private ServiceConnection sc = new ServiceConnection() {  @Override  public void onServiceConnected(ComponentName name, IBinder service) {  //connect Service   musicService = IMusicControlService.Stub.asInterface(service);  }  @Override  public void onServiceDisconnected(ComponentName name) {     //disconnect Service   musicService = null;  } };  @Override public void onDestroy(){  super.onDestroy();    if(sc != null){   unbindService(sc);    // unBindService  } }}

Remote Service流程總結:

1、 Activity(客戶端)中,Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");構建intent,然後bindService(intent, sc, Context.BIND_AUTO_CREATE);繫結服務

2、 Activity(客戶端)中,通過ServiceConnection()過載onServiceConnected()建立連線,獲取Service.Stub例項;onServiceDisconnected()釋放連線(與bindService類似)

3、 Service中,通過過載onBind(Intent intent) 返回Service.Stub例項,但Service.Stub類是由aidl檔案生成的介面類中的一個內部類Stub類,Service來繼承該Stub類

4、 Activity中,通過操作Service例項(musicService),執行音樂播放操作(play、pause、stop等)


原始碼下載



參考推薦:

Service (android developer)

Android Service 服務(一)—— Service

Android Service 服務(二)—— BroadcastReceiver

android中service和aidl詳細整理

Android Service AIDL

android筆記--Service與AIDL


           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述