Bound Services邦定服務html
A bound service is the server in a client-server interface. A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication (IPC). A bound service typically lives only while it serves another application component and does not run in the background indefinitely.
邦定服務是一個在客戶端服務接口的服務.一個邦定的服務容許組件邦定到服務,發送請求,接收響應,和事件執行進程間通訊(IPC).一個邦定的服務只有當他服務於其餘組件時才存在(live),而且不會無限在後臺運行。
This document shows you how to create a bound service, including how to bind to the service from other application components. However, you should also refer to the
Services document for additional information about services in general, such as how to deliver notifications from a service, set the service to run in the foreground, and more.
這個文檔告訴你怎樣建立一個邦定的服務,包括怎麼把其餘應用組件邦定到服務。可是關於服務的其餘信息,好比怎麼從服務傳送一個通知器,將服務設置在前臺運行等等,你應該參考
Services文檔.
The Basics基礎
A bound service is an implementation of the
Service class that allows other applications to bind to it and interact with it. To provide binding for a service, you must implement the
onBind() callback method. This method returns an
IBinder object that defines the programming interface that clients can use to interact with the service.
A client can bind to the service by calling
bindService(). When it does, it must provide an implementation of
ServiceConnection, which monitors the connection with the service. The
bindService() method returns immediately without a value, but when the Android system creates the connection between the client and service, it calls
onServiceConnected() on the
ServiceConnection, to deliver the
IBinder that the client can use to communicate with the service.
Multiple clients can connect to the service at once. However, the system calls your service's
onBind() method to retrieve the
IBinder only when the first client binds. The system then delivers the same
IBinder to any additional clients that bind, without calling
onBind() again.
When the last client unbinds from the service, the system destroys the service (unless the service was also started by
startService()).
When you implement your bound service, the most important part is defining the interface that your
onBind() callback method returns. There are a few different ways you can define your service's
IBinder interface and the following section discusses each technique.
Creating a Bound Service建立邦定服務
When creating a service that provides binding, you must provide an
IBinder that provides the programming interface that clients can use to interact with the service. There are three ways you can define the interface:
當建立一個帶有邦定的服務時,你必須提供一個
IBinder
,
它是一個編程接口,客戶端用它來與服務通訊。定義該接口的方法有三種:
If your service is private to your own application and runs in the same process as the client (which is common), you should create your interface by extending the
Binder class and returning an instance of it from
onBind(). The client receives the
Binder and can use it to directly access public methods available in either the
Binder implementation or even the
Service.
This is the preferred technique when your service is merely a background worker for your own application. The only reason you would not create your interface this way is because your service is used by other applications or across separate processes.
當你的服務僅僅只用於作爲你的應用的後臺工做者,這將是首先選擇的技術。你不這樣建立你的接口的惟一緣由是:你的服務用於其餘應用或者要跨進程通訊
If you need your interface to work across different processes, you can create an interface for the service with a
Messenger. In this manner, the service defines a
Handler that responds to different types of
Message objects. This
Handler is the basis for a
Messenger that can then share an
IBinder with the client, allowing the client to send commands to the service using
Message objects. Additionally, the client can define a
Messenger of its own so the service can send messages back.
This is the simplest way to perform interprocess communication (IPC), because the
Messenger queues all requests into a single thread so that you don't have to design your service to be thread-safe.
這是執行進程間通訊的最簡單的方法,由於
Messenger隊列的全部請求,都在一個單一的線程中,因此你沒必要去爲你的服務設置線程安全.
Using AIDL使用AIDL(Android接口定義語言)
AIDL (Android Interface Definition Language) performs all the work to decompose objects into primitives that the operating system can understand and marshall them across processes to perform IPC. The previous technique, using a
Messenger, is actually based on AIDL as its underlying structure. As mentioned above, the
Messenger creates a queue of all the client requests in a single thread, so the service receives requests one at a time. If, however, you want your service to handle multiple requests simultaneously, then you can use AIDL directly. In this case, your service must be capable of multi-threading and be built thread-safe.
AIDL執行全部的工做,把對象分解成操做系統能理解的原語,並把它們編組以跨進程通訊。前面提到的使用
Messenger的技術,其實是基於AIDL作爲它的底層架構的。就上面所提到的,
Messenger在一個線程中,爲他的客戶端全部的請求建立一個隊列,因此服務一次只能接收一個請求。然而,若是你想要你的服務同時處理多個服務,那麼你能夠直接使用AIDL.這樣的話,你的服務必須能同時處理多線程而且被設計成多線程安全的。
To use AIDL directly, you must create an
.aidl
file that defines the programming interface. The Android SDK tools use this file to generate an abstract class that implements the interface and handles IPC, which you can then extend within your service.
要直接使用AIDL,你必須建立一個.aidl的文件,這個文件定義了編程接口。Android SDK使用這個文件產生一個實現此接口的抽象類,而且處理IPC,而後在你的服務中繼承這個類.
Note: Most applications
should not use AIDL to create a bound service, because it may require multithreading capabilities and can result in a more complicated implementation. As such, AIDL is not suitable for most applications and this document does not discuss how to use it for your service. If you're certain that you need to use AIDL directly, see the
AIDL document.
注意:大多數應用應該不要使用AIDL建立邦定服務,由於它可能須要多線程能力,而且致使更多複雜的實現。所以,AIDL不適合大多數應用,而且這個文檔不討論爲你的服務怎樣使用它。若是你肯定你須要直接使用AIDL,請看AIDL文檔.
Extending the Binder class繼承Binder類
If your service is used only by the local application and does not need to work across processes, then you can implement your own
Binder class that provides your client direct access to public methods in the service.
若是你的服務只用於局部的應用,而且不須要跨進程工做,那麼你能夠實現本身的Binder類,它爲你的客戶端提供直接訪問服務的公共方法
Note: This works only if the client and service are in the same application and process, which is most common. For example, this would work well for a music application that needs to bind an activity to its own service that's playing music in the background.
注意:繼承Binder類,只工做於:假設你的客戶端和服務端都在同一個應用和進程中,這也是最多見的狀況.好比,一個音樂應用須要邦定一個活動到它本身的後臺音樂播放服務,它將工做得很好。
Here's how to set it up:這裏是如何設置它:
- In your service, create an instance of Binder that either: 在你的服務裏,建立下面之一的Binder實例:
- contains public methods that the client can call包括一個客戶端調用的公共方法
- returns the current Service instance, which has public methods the client can call返回當前Service實例,它有客戶端能夠調用的公共方法
- or, returns an instance of another class hosted by the service with public methods the client can call返回一個service持有的類的實例,它帶有一個客戶端可調用的公共方法
- Return this instance of Binder from the onBind() callback method.從onBind()回調方法返回Binder的this實例.
- In the client, receive the Binder from the onServiceConnected() callback method and make calls to the bound service using the methods provided.在客戶端,接收來自onServiceConnected()回調的Binder,而且用它提供的方法產生對service的調用.
Note: The reason the service and client must be in the same application is so the client can cast the returned object and properly call its APIs. The service and client must also be in the same process, because this technique does not perform any marshalling across processes.
注意:客戶端和服務必須在同一個應用的緣由是,客戶端能夠對返回的對象進行類型轉換而且適當的調用它的APIs.這個服務和客戶端也必須在同一個進程,緣由是這個技術不能執行任何編組跨進程.
For example, here's a service that provides clients access to methods in the service through a
Binder implementation:
好比,這個服務,它經過實現
Binder,爲客戶端提供了訪問服務中的方法。
publicclassLocalServiceextendsService{
// Binder given to clients給客戶端的Binders
private final IBinder mBinder = new LocalBinder();
// Random number generator隨機數產生器
private 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.用於客戶端的類,由於咱們知道這個服務老是與它的客戶端運行在同一個進程中的,因此咱們不須要處理IPC
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods返回這個實例的本地服務,以便客戶端能夠調用本地方法
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
The
LocalBinder
provides the
getService()
method for clients to retrieve the current instance of
LocalService
. This allows clients to call public methods in the service. For example, clients can call
getRandomNumber()
from the service.
LocalBinder提供一個方法,給用戶取回LocalService的實例.這容許全部的客戶調用這個服務的公共方法。好比,客戶端能夠調用服務的getRandomNumber()
Here's an activity that binds to
LocalService
and calls
getRandomNumber()
when a button is clicked:下面是一個邦定到
LocalService的活動,而且當按一個按鈕時,調用getRandomNumber()方法
publicclassBindingActivityextendsActivity{
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (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)
*當一個按鈕被點擊時,被調用這個按鈕在佈局文件用經過android:onClick屬性加入進來的
*/
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()
定義一service binding的回調方法,傳遞給bindService()*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance咱們已經邦定到LocalService,轉換IBinder而且,獲取LocalService實例
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
The above sample shows how the client binds to the service using an implementation of
ServiceConnection and the
onServiceConnected() callback. The next section provides more information about this process of binding to the service.
Note: The example above doesn't explicitly unbind from the service, but all clients should unbind at an appropriate time (such as when the activity pauses).
注意.上面的例子沒有顯示的從服務解除邦定,可是全部的客戶端應在適當的時候解除邦定(好比活動中止)
Using a Messenger使用信使
If you need your service to communicate with remote processes, then you can use a
Messenger to provide the interface for your service. This technique allows you to perform interprocess communication (IPC) without the need to use AIDL.
若是你的服務要與遠程過程進行通訊,那你能夠爲你的服務提供一個
Messenger接口。這一技術能讓你在沒有AIDL的狀況下執行進程間通訊.
In this way, there are no "methods" for the client to call on the service. Instead, the client delivers "messages" (
Message objects) that the service receives in its
Handler.
經過這種方式,在服務端不須要調用客戶端的」方法methods」,而是,而客戶端傳遞」消息」,服務端在它的
Handler中接收該消息.
publicclassMessengerServiceextendsService{
/** Command to the service to display a message給服務顯示一個消息的命令 */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.處理來自客戶端的信息
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO://接到這個消息,顯示一個Toast
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.當邦定到服務,咱們返回一個接口到咱們的messenger.用於發送消息到服務
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
All that a client needs to do is create a
Messenger based on the
IBinder returned by the service and send a message using
send(). For example, here's a simple activity that binds to the service and delivers the
MSG_SAY_HELLO
message to the service:
publicclassActivityMessengerextendsActivity{
/** Messenger for communicating with the service. 與服務通訊的Messenger*/
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. 標誌,表示是否咱們對Service調用bind*/
boolean mBound;
/**
* Class for interacting with the main interface of the service.與服務主接口通訊的類
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
//當與服務創建了聯接,給予咱們與服務進行交互的對象時,這個方法被調用,咱們使用一個Messenger與服務通訊,因此這裏咱們獲得一個來自raw IBinder對象的客戶端的reprentation
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed當與服務的聯接,出現意外的斷聯—意思,它的進程崩潰。.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value使用支持的’what’值,建立併發送一個消息給服務
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
Notice that this example does not show how the service can respond to the client. If you want the service to respond, then you need to also create a
Messenger in the client. Then when the client receives the
onServiceConnected() callback, it sends a
Message to the service that includes the client's
Messenger in the
replyTo parameter of the
send() method.
Binding to a Service邦定到服務s
Application components (clients) can bind to a service by calling
bindService(). The Android system then calls the service's
onBind() method, which returns an
IBinder for interacting with the service.應用組件能夠調用
bindService()方法邦定到服務,Android系統而後調用服務的
onBind()方法,該方法返回一個用於與服務交互的
IBinder
Note: Only activities, services, and content providers can bind to a service—you
cannot注意只有活動,服務和內容提供者能邦定到一個服務,一個broadcast接收者,不能邦一到服務 bind to a service from a broadcast receiver.
So, to bind to a service from your client, you must: 因此從你的客戶端邦定到服務必須是:
- Implement ServiceConnection. 實現服務聯接
Your implementation must override two callback methods:實現中必需要複寫的兩個方法
The Android system calls this when the connection to the service is unexpectedly lost, such as when the service has crashed or has been killed. This is
not當服務的聯出現異常丟失時,好比崩潰或者被殺掉,系統調用它.當客戶端解除幫定時,系統不調用 called when the client unbinds.
- Call bindService(), passing the ServiceConnection implementation. 調用bindService()方法,傳遞ServiceConnection的實現
- When the system calls your onServiceConnected() callback method, you can begin making calls to the service, using the methods defined by the interface.當系統調用你的onServiceConnected()回訪方法時,你可使用由接口定義的方法,對服務發起一個調用.
- To disconnect from the service, call unbindService(). 要從服務解除聯接,調用unbindService()
When your client is destroyed, it will unbind from the service, but you should always unbind when you're done interacting with the service or when your activity pauses so that the service can shutdown while its not being used. (Appropriate times to bind and unbind is discussed more below.)當你的客戶端被銷燬時,它將從服務解除邦定,但你應老是當你的交互完成時,或者當你的活動暫停時解除邦定,以便當它的再也不使用時服務可關閉(適當的時候邦定或者解除邦定在下面討論)
For example, the following snippet connects the client to the service created above by
extending the Binder class, so all it must do is cast the returned
IBinder to the
LocalService
class and request the
LocalService
instance:
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public 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 unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};
Intent intent =newIntent(this,LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Additional notes附加註意事項
Here are some important notes about binding to a service:下面是邦定到一個服務的一些重要注意的事項.
- You should always trap DeadObjectException exceptions, which are thrown when the connection has broken. This is the only exception thrown by remote methods.你應該老是處理(trap)DeadObjectException異常.當聯接崩潰時,惟一由遠程方法拋出的異常
- Objects are reference counted across processes. 跨進程的對象引用計數
- You should usually pair the binding and unbinding during matching bring-up and tear-down moments of the client's lifecycle. For example: 你一般應將邦定和解除邦定,成對的出如今客戶端生命週期相對應的時刻。好比:
- If you only need to interact with the service while your activity is visible, you should bind during onStart() and unbind during onStop().若是隻有當你的活動可見時才須要與服務交互,那麼你應該在方法中邦定,在方法中解除邦定
- If you want your activity to receive responses even while it is stopped in the background, then you can bind during onCreate() and unbind during onDestroy(). Beware that this implies that your activity needs to use the service the entire time it's running (even in the background), so if the service is in another process, then you increase the weight of the process and it becomes more likely that the system will kill it.若是你但願你的活動,即便中止在後臺,也能接收響應,那麼你能夠在方法中邦定,在方法中銷燬。注意,這意味着,在你的活動的整個運行時間都要使用服務(即便是活動在後臺),因此若是服務在其餘的進程中,那麼你可能增長你服務的比重(weight),而且它可能變得極有可能被殺掉.
Note: You should usually
not bind and unbind during your activity's
onResume() and
onPause(), because these callbacks occur at every lifecycle transition and you should keep the processing that occurs at these transitions to a minimum. Also, if multiple activities in your application bind to the same service and there is a transition between two of those activities, the service may be destroyed and recreated as the current activity unbinds (during pause) before the next one binds (during resume). (This activity transition for how activities coordinate their lifecycles is described in the
Activities document.)
注意:你不該常常在
onResume()方法和
onPause()方法中邦定和解除邦定.所以這些回調方法常常在活動的生命週期轉換時調用,而且你應保持這些轉換使用的時間最少化.還有,若是在你的應用中有多個活動,邦定到這一個服務上,並在某兩個活動之間有轉換,該服務可能在當前活動解除邦定,下一個邦定前,銷燬並重建立了。(活動是怎樣在轉換中定位生命週期,在
Activities文檔中描述)
Managing the Lifecycle of a Bound Service管理邦定服務的生命週期
When a service is unbound from all clients, the Android system destroys it (unless it was also started with
onStartCommand()). As such, you don't have to manage the lifecycle of your service if it's purely a bound service—the Android system manages it for you based on whether it is bound to any clients.
當一個服務從全部客戶端解除邦定,Android系統銷燬它(除非它也是用
onStartCommand()方法啓動的)。所以,若是你的服務純粹是一個邦定服務,你不須要管理它的生命週期---系統根據它是否邦定到任何客戶端來管理它的生命週期.
However, if you choose to implement the
onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be
started. In this case, the service runs until the service stops itself with
stopSelf() or another component calls
stopService(), regardless of whether it is bound to any clients.
Additionally, if your service is started and accepts binding, then when the system calls your
onUnbind() method, you can optionally return
true
if you would like to receive a call to
onRebind() the next time a client binds to the service (instead of receiving a call to
onBind()).
onRebind() returns void, but the client still receives the
IBinder in its
onServiceConnected() callback. Below, figure 1 illustrates the logic for this kind of lifecycle.

For more information about the lifecycle of an started service, see the
Services document.關於啓動服務的生命週期更多信息,看
Services文檔