綁定服務(wù)
綁定服務(wù)是客戶端-服務(wù)器接口中的服務(wù)器。綁定服務(wù)可讓組件(例如 Activity)綁定到服務(wù)、發(fā)送請求、接收響應(yīng),甚至執(zhí)行進(jìn)程間通信 (IPC)。 綁定服務(wù)通常只在為其他應(yīng)用組件服務(wù)時(shí)處于活動狀態(tài),不會無限期在后臺運(yùn)行。
Sevice
以下這個服務(wù)可讓客戶端通過 Binder 實(shí)現(xiàn)訪問服務(wù)中的方法
public class LocalService extends Service {
IBinder mBinder = new LocalBinder();
private final Random mGenerator = new Random();
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
Client
public class MainActivity extends Activity {
LocalService mService;
Button button;
Boolean mBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mBound) {
int num = mService.getRandomNumber();
Toast.makeText(getApplicationContext(), String.valueOf(num), Toast.LENGTH_LONG).show();
}
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
LocalService.LocalBinder binder = (LocalService.LocalBinder) iBinder;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
}
MessagerSevice
以下是一個使用 Messenger 接口的簡單服務(wù)示例:
public class MessengerService extends Service {
static final int MSG_SAY_HELLO = 1;
Messenger mMessenger = new Messenger(new IncomingHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
}
ActivityMessager
客戶端只需根據(jù)服務(wù)返回的 IBinder 創(chuàng)建一個 Messenger,然后利用 send() 發(fā)送一條消息。例如,以下就是一個綁定到服務(wù)并向服務(wù)傳遞 MSG_SAY_HELLO 消息的簡單 Activity:
public class ActivityMessenger extends Activity {
Messenger mService = null;
boolean mBound;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mBound)
return;
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mService = new Messenger(iBinder);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
mService = null;
}
};
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mServiceConnection);
mBound = false;
}
}
}
注:只有 Activity、服務(wù)和內(nèi)容提供程序可以綁定到服務(wù)—您無法從廣播接收器綁定到服務(wù)。
綁定到服務(wù)
因此,要想從您的客戶端綁定到服務(wù),您必須:
- 實(shí)現(xiàn) ServiceConnection。
- 調(diào)用 bindService() 以傳遞 ServiceConnection 實(shí)現(xiàn)。
- 當(dāng)系統(tǒng)調(diào)用您的 onServiceConnected() 回調(diào)方法時(shí),您可以使用接口定義的方法開始調(diào)用服務(wù)。
- 要斷開與服務(wù)的連接,請調(diào)用 unbindService()。
附加說明
- 應(yīng)該始終捕獲 DeadObjectException 異常,它是在連接中斷時(shí)引發(fā)的異常。這是遠(yuǎn)程方法引發(fā)的唯一異常
- 對象是跨進(jìn)程計(jì)數(shù)的引用
- 如果您希望 Activity 在后臺停止運(yùn)行狀態(tài)下仍可接收響應(yīng),則可在 onCreate() 期間綁定,在 onDestroy() 期間取消綁定。這意味著您的 Activity 在其整個運(yùn)行過程中(甚至包括后臺運(yùn)行期間)都需要使用服務(wù),因此如果服務(wù)位于其他進(jìn)程內(nèi),那么當(dāng)您提高該進(jìn)程的權(quán)重時(shí),系統(tǒng)終止該進(jìn)程的可能性會增加
注:通常情況下,切勿在 Activity 的 onResume() 和 onPause() 期間綁定和取消綁定,因?yàn)槊恳淮紊芷谵D(zhuǎn)換都會發(fā)生這些回調(diào),您應(yīng)該使發(fā)生在這些轉(zhuǎn)換期間的處理保持在最低水平。此外,如果您的應(yīng)用內(nèi)的多個 Activity 綁定到同一服務(wù),并且其中兩個 Activity 之間發(fā)生了轉(zhuǎn)換,則如果當(dāng)前 Activity 在下一次綁定(恢復(fù)期間)之前取消綁定(暫停期間),系統(tǒng)可能會銷毀服務(wù)并重建服務(wù)。 (Activity文檔中介紹了這種有關(guān) Activity 如何協(xié)調(diào)其生命周期的 Activity 轉(zhuǎn)換。)
管理綁定服務(wù)的生命周期
- 當(dāng)服務(wù)與所有客戶端之間的綁定全部取消時(shí),Android 系統(tǒng)便會銷毀服務(wù)(除非還使用 onStartCommand() 啟動了該服務(wù))
- 不過,如果您選擇實(shí)現(xiàn) onStartCommand() 回調(diào)方法,則您必須顯式停止服務(wù),因?yàn)橄到y(tǒng)現(xiàn)在已將服務(wù)視為已啟動。在此情況下,服務(wù)將一直運(yùn)行到其通過 stopSelf() 自行停止,或其他組件調(diào)用 stopService() 為止,無論其是否綁定到任何客戶端。
- 此外,如果您的服務(wù)已啟動并接受綁定,則當(dāng)系統(tǒng)調(diào)用您的 onUnbind() 方法時(shí),如果您想在客戶端下一次綁定到服務(wù)時(shí)接收 onRebind() 調(diào)用(而不是接收 onBind() 調(diào)用),則可選擇返回 true。onRebind() 返回空值,但客戶端仍在其 onServiceConnected() 回調(diào)中接收 IBinder。下文圖 1 說明了這種生命周期的邏輯。