Bound Services
原文URL:Bound Services
(1)
Bound service在客戶/服務器模式中充當服務端。一個Bound Service允許組件(比如Activities)綁定到該Service上,發送請求,接收響應,甚至是進行進程間通信(IPC)。一個Bound Service只存活在當它為其他的應用組件服務的時候,并且不會永遠在后臺運行下去。
本文檔將向你展示如何創建一個Bound Service ,包括如何從其他的應用組件綁到到該Service。但是,你也應該參考一下Services文檔中的關于Services的常識信息,例如,如何從一個Service提交Notifications,將Service 設置為前臺運行等等。
(2)The Basics
Bound Service 是Service類的子類,它允許其他的應用程序綁定該Service,并和它進行交互。為了使一個Service 具有綁定功能,你必須實現onBind()回調方法。該方法返回一個IBinder對象,該對象定義了clients能用來與該Service 進行交互的編程接口。
?client 可以通過調用bindService()方法綁定該Service。當進行綁定時,必須提供一個ServiceConnection的實現,它用來監視與Service 的連接狀態。bindService()方法會立即返回,并且沒有返回值,但是,當Android 系統創建client與Service 之間的連接時,系統會調用ServiceConnection中的onServiceConnection()方法,把IBinder 對象交給client,這樣的話,client可以使用該對象與Service 進行交互。
多個client可以同時連接該Service。但是,系統只會在第一個client綁定的時候調用你Service 的onBind()方法獲取IBinder對象。然后系統會把這一個IBinder對象交給后續綁定到該Service的其他的client,而不會再調用onBind()方法。
當最后一個client解除與該Service 的綁定關系后,系統會銷毀該Service (除非該Service 也是用startService()方法啟動創建的)。
當你實現你的Bound Service 時,最重要的一點就是定義你的onBind()回調方法返回的IBinder ?接口。有三種不同的方式可以定義你的Service 的IBinder 接口,下面將一一介紹各種方法。
(3)Creating a Bound Service
當創建一個具有綁定功能的Service 時,你必須提供一個IBinder 接口,它提供了client用來與該Service 交互的編程接口。你可以有三種方式定義此接口:
如果你的Service 只在你自己的應用中使用,并且和client運行在同一個進程中(這是一普遍的情況),你應該通過繼承Binder類并從onBind()方法返回它的一個實例的方式創建該接口。client可以接收該Binder對象并使用它直接調用Binder實現類的或者甚至是Service 的public 方法。
如果你的Service 僅僅只是在你的自己應用程度中做一些后臺工作,這是一種首選方式。你不能使用此種方式創建IBinder接口的唯一情況就是你的Service 要被其他的應用程序使用,或者跨躍不同的進程。
如果你的Service 只是在自己的應用程序中使用,并且不需要進行跨進程工作,那么你可以通過繼承Binder 類來實現你的Binder 類,它可以使client能夠直接調用Service 的public 方法。
注意:此種方式只適用于client和service在同一個應用程序和進程中,這是最普遍的情況。例如,XXX
下面是創建過程:
1》在你的Service中,創建一個Binder的實例:
1.1》這個Binder實例含有client要調用的public 方法
1.2》這個Binder實例返回當前的Service實例,該Service 含有client可以調用的public 方法(ps:下面的事例就是采用這種方法)
1.3》或者,XXX
2》從Service的onBind()方法中返回該Binder的實例
3》在client中,從onServiceConnected()回調方法接收此Binder對象實例并調用綁定的Service提供的方法
For example, here's a service that provides clients access to methods in the service through a Binder implementation:
package com.mytest.servicetest;import java.util.Random;import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log;public class LocalService extends Service {// Binder given to clientsprivate final IBinder mBinder = new LocalBinder();// Random number generatorprivate final Random mGenerator = new Random();/*** Class used for the client Binder. Because we know this service always* runs in the same process as its clients, we don't need to deal with IPC.*/public class LocalBinder extends Binder {LocalService getService() {// Return this instance of LocalService so clients can call public// methodsreturn LocalService.this;}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn mBinder;}/** method for clients */public int getRandomNumber() {return mGenerator.nextInt(100);} }
LocalBinder提供了getService()方法,client通過此方法得到LocalService的實例。client可以通過該實例調用Service 中的public 方法。例如,client可以調用Service 中的getRandomNumber()方法。
下面是一個要綁定LocalService的Activity,并且在該Activity 中,當點擊按鈕時,調用LocalService 中的getRandomNumber()方法。
public class BindingActivity extends Activity {LocalService mService;boolean mBound = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);}@Overrideprotected void onStart() {super.onStart();// Bind to LocalServiceIntent intent = new Intent(this, LocalService.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onStop() {super.onStop();// Unbind from the serviceif (mBound) {unbindService(mConnection);mBound = false;}}/** Called when a button is clicked (the button in the layout file attaches to* this method with the android:onClick attribute) */public void onButtonClick(View v) {if (mBound) {// Call a method from the LocalService.// However, if this call were something that might hang, then this request should// occur in a separate thread to avoid slowing down the activity performance.int num = mService.getRandomNumber();Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();}}/** Defines callbacks for service binding, passed to bindService() */private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName className,IBinder service) {// We've bound to LocalService, cast the IBinder and get LocalService instanceLocalBinder binder = (LocalBinder) service;mService = binder.getService();mBound = true;}@Overridepublic void onServiceDisconnected(ComponentName arg0) {mBound = false;}}; }
以上事例展示了client如何使用ServiceConnection實例以及onServiceConnected()回調方法綁定Service。下面詳細介紹 一下綁定Service的過程。
應用程序組件(Clients)可以調用bindService()方法綁定一個service。然后Android 系統會調用service 的onBind()方法,該方法會返回一個IBinder對象,用來與service 進行交互。
綁定過程是異步的。也就是說,bindService()方法會立即返回并且不會向client返回IBinder對象。為了接收IBinder對象,client必須要創建一個ServiceConnection的實例,并把該實例傳遞給bindService()方法。ServiceConnection類包含一個回調方法(ps:也就是onServiceConnected()回調方法),Android系統就是用這個回調方法向client返回IBinder 對象的。
注意:只有activities,services和content providers可以綁定service--不可以用broadcast receiver綁定service
從client綁定service時,你必須:
1.實例化ServiceConnection.
實例時必須要重寫 兩個回調方法:
onServiceConnected()
Android系統會調用此方法將service中的onBind()方法返回的IBinder對象交給client.
onServiceDisconnected()
當client與service的連接忽然斷開時,Android系統會調用此方法,比如當service突然崩潰時或者service被kill的時候。
但是,當client與service解除綁定時不會調用此方法。
2.client調用bindService()方法,并將實例化的ServiceConnection對象傳遞給它。
3.當Android系統調用onServiceConnected()方法時,你可以調用service中定義的接口方法。
4.調用unbindService()方法,解除與service 的綁定關系。
當client銷毀時,client將解除與service的綁定關系,但是你應該總是在使用完service之后或者是當Activity暫停時解除綁定,這樣的話,service 就可以在它沒有被使用的時候停止了。(綁定與解除綁定的合適時機將在下面討論。)
LocalService mService; private ServiceConnection mConnection = new ServiceConnection() {// Called when the connection with the service is establishedpublic void onServiceConnected(ComponentName className, IBinder service) {// Because we have bound to an explicit// service that is running in our own process, we can// cast its IBinder to a concrete class and directly access it.LocalBinder binder = (LocalBinder) service;mService = binder.getService();mBound = true;}// Called when the connection with the service disconnects unexpectedlypublic void onServiceDisconnected(ComponentName className) {Log.e(TAG, "onServiceDisconnected");mBound = false;} };
Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
總結
以上是生活随笔為你收集整理的Bound Services的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Service基本组成 (一)
- 下一篇: Managing the Lifecyc