Messenger可以翻譯為信使,通過它可以在不同進程中傳遞Message對象,在Message 中放入我們需要傳遞的數據,就可以輕松實現數據的進程間傳遞了。Messenger是一種輕量級的IPC方案,它的底層實現是AIDL。Messenger的使用方法很簡單,它對AIDL做了封裝,使得我們可以更簡單的進行進程間通信。同時,由于它一次處理一個請求,因此在服務端我們不用考慮。
1 服務端進程
首先我們需要在服務端創建一個Service來處理客戶端的連接請求,同時創建一個Handler來通過它來創建一個Messenger對象,然后在Service的onBind中返回這個Messenger對象底層的Binder即可。
2 客戶端進程
在客戶端進程中,首先要綁定服務端的Service,綁定成功后用服務端返回的IBinder對象創建一個Messenger,通過這個Messenger就可以向服務端發送消息了,發消息類型為Message對象。如果需要服務端能夠回應客戶端,就和服務端一樣,我們還需要創建一個Handler并創建一個新的Messenger,并把這個Messenger對象通過Message的replyTo參數傳遞給服務端,服務端通過這個replyTo參數就可以回應客戶端。
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MyConstants.MES_FROM_CLIENT:
Log.d("zhouzhuo","receive msg from Client:"+msg.getData().getString("msg"));
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null,MyConstants.MES_FROM_SERVICE);
Bundle bundle = new Bundle();
bundle.putString("reply","恩,你的消息已經收到,稍后回復你");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
}
private final Messenger messenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("zhouzhuo","==Binder===");
return messenger.getBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
客戶端的實現,首先需要綁定遠程進程的MessengerService,綁定成功后,根據服務端返回的binder對象創建Messenger對象并使用此對象向服務端發送消息。代碼如下:
public class MessengerActivity extends Activity {
private static final String TAG = "MessengerActivity";
private Messenger mSerVie;
//handler 將會接收這個消息
private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MyConstants.MES_FROM_SERVICE:
Log.i("zhouzhuo", "receive msg from Service:" + msg.getData().getString("reply"));
break;
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mSerVie = new Messenger(service);
Log.d("zhouzhuo","bind service");
Message msg = Message.obtain(null,MyConstants.MES_FROM_CLIENT);
Bundle data = new Bundle();
data.putString("msg","hello,this is client");
msg.setData(data);
//將消息
msg.replyTo = mGetReplyMessenger;
try {
mSerVie.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
Intent intent = new Intent(this,MessengerService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
}
}
在Messenger中進行數據傳遞必須將數據放入Message中,而Messenger和Message都實現了Parcelable接口,因此可以進行跨進程傳輸。簡單來說,Message中所支持的數據類型就是Messenger所支持的傳輸類型。實際上,通過Messenger來傳輸Message,Message中能使用的載體只有what,arg1,arg2,Bundle以及replyTo.Message中的另一個字段object在同一進程中是很實用的,但是在進程間通信的時候,在Android 2.2 以前的object字段不支持跨進程傳輸,即使2.2以后,也僅僅是系統提供的實現了Parcelable接口的對象才能通過他來傳輸,非系統的Parcelable對象無法通過obj字段來傳輸,這也導致object的實用性大大降低,所幸我們還有Bundle,Bundle中可以支持大量的數據類型。
3 代碼運行后的結果
ne D/zhouzhuo: ==Binder===
01-02 13:59:33.175 439-439/com.zhouzhuo.messengerone D/mali_winsys: new_window_surface returns 0x3000
01-02 13:59:33.195 439-439/com.zhouzhuo.messengerone D/zhouzhuo: bind service
01-02 13:59:33.210 439-439/com.zhouzhuo.messengerone D/zhouzhuo: receive msg from Client:hello,this is client
01-02 13:59:33.210 439-439/com.zhouzhuo.messengerone I/zhouzhuo: receive msg from Service:恩,你的消息已經收到,稍后回復你
01-02 13:59:46.725 439-445/com.zhouzhuo.messengerone I/jdwp: Ignoring second debugger -- accepting and dropping
4 項目地址