一.Messenger簡介
???????與AIDL進(jìn)程間通信作用一樣,Messenger是基于Message對象進(jìn)行跨進(jìn)程通信的,類似于Handler發(fā)送消息實(shí)現(xiàn)子線程和UI線程進(jìn)行通信,此外,還支持記錄客戶端對象的Messenger,然后可以實(shí)現(xiàn)一對多的通信;甚至作為一個(gè)轉(zhuǎn)接處,任意兩個(gè)進(jìn)程都能通過服務(wù)端進(jìn)行通信。
???????普通的進(jìn)程間通信,需要服務(wù)端自己提供AIDL接口文件,然后本地實(shí)現(xiàn)Stub內(nèi)方法,客戶端需要引入方可進(jìn)行通信;
???????Messenger是系統(tǒng)提供統(tǒng)一的AIDL接口文件,并且由Handler來實(shí)現(xiàn)Stub內(nèi)方法,服務(wù)端在Handler內(nèi)處理即可,客戶端不需要引入,直接可以通信;
二.Messenger實(shí)現(xiàn)流程
a.服務(wù)端實(shí)現(xiàn)
???????1.創(chuàng)建一個(gè)Handler對象,并實(shí)現(xiàn)handleMessage方法,用于接收來自客戶端的消息并作處理;
???????2.創(chuàng)建一個(gè)Messenger(送信人),封裝Handler;
???????3.用Messenger的getBinder()方法獲取一個(gè)IBinder對象,通過onBind返回給客戶端;
???????代碼如下:
public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
private MessengerHandler mHandler = new MessengerHandler();
private Messenger mMessenger = new Messenger(mHandler);
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//取出客戶端的消息內(nèi)容
Bundle bundle = msg.getData();
String clientMsg = bundle.getString("client");
Log.i(TAG,"來自客戶端的消息:"+clientMsg);
//新建一個(gè)Message對象,作為回復(fù)客戶端的對象
Message message = Message.obtain();
Bundle bundle1 = new Bundle();
bundle1.putString("server","已收到消息");
message.setData(bundle1);
try {
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
???????服務(wù)端接受到客戶端的消息,其實(shí)與線程間通信一樣,也是在handleMessage方法中進(jìn)行處理;
???????如果服務(wù)端需要回復(fù)客戶端,則需要獲取到客戶端攜帶過來的Messenger對象(即msg.replyTo),通過msg.replyTo.send()給客戶端發(fā)送信息。
b.客戶端實(shí)現(xiàn)
???????1.綁定服務(wù),創(chuàng)建ServiceConnection并在其中使用IBinder將Messenger實(shí)例化;
???????2.使用Messenger向服務(wù)端發(fā)送消息;
???????3.接收服務(wù)端發(fā)送過來的message;
???????4.解綁服務(wù);
???????實(shí)現(xiàn)如下:
public class MyActivity extends Activity implements View.OnClickListener {
private static final String TAG = MyActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bindService = findViewById(R.id.bindService);
Button unBindService = findViewById(R.id.unBindService);
bindService.setOnClickListener(this);
unBindService.setOnClickListener(this);
}
public void onClick(View view) {
switch (view.getId()){
case R.id.bindService:
Intent intent = new Intent();
intent.setAction("com.hly.learn.server.action");
bindService(intent,mConnection,BIND_AUTO_CREATE);
break;
case R.id.unBindService:
unbindService(mConnection);
break;
default:
break;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取服務(wù)端關(guān)聯(lián)的Messenger對象
Messenger mService = new Messenger(service);
//創(chuàng)建Message對象
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("client","hello");
message.setData(bundle);
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
}
}
???????客戶端在綁定服務(wù)之后,在ServiceConnection中通過IBinder得到Messenger對象(mService),然后用mService的send方法把Message作為形參發(fā)送給服務(wù)端。
雙向通信實(shí)現(xiàn)
???????如果服務(wù)端收到消息需要回復(fù)客戶端,應(yīng)該怎么實(shí)現(xiàn)呢?
???????客戶端也需要?jiǎng)?chuàng)建一個(gè)Messenger對象,接著創(chuàng)建一個(gè)對應(yīng)的處理Handler對象,最后在onServiceConnected方法中,把Messenger對象賦值給message.replyTo,通過mService.send(message)方法發(fā)送給服務(wù)端,服務(wù)端可以通過replyTo的messenger對象給客戶端發(fā)消息,從而完成雙向通信,實(shí)現(xiàn)如下:
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取服務(wù)端關(guān)聯(lián)的Messenger對象
Messenger mService=new Messenger(service);
//創(chuàng)建Message對象
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("client","hello");
message.setData(bundle);
//在message中添加一個(gè)回復(fù)mReplyMessenger對象,server端可通過此來給client發(fā)消息
message.replyTo = mReplyMessenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
private ReplyHandler mReplyHandler = new ReplyHandler();
private Messenger mReplyMessenger = new Messenger(mGetReplyHandler);
public static class ReplyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle bundle = msg.getData();
String serviceMsg = bundle.getString("server");
Log.i(TAG, "來自服務(wù)端的回復(fù):"+serviceMsg);
}
}
???????服務(wù)端在AndroidManifest.xml中對service進(jìn)行配置:
<service android:name=".model.MyService"
android:exported="true"
<intent-filter>
<action android:name="com.hly.learn.server.action" />
</intent-filter>
</service>
???????其實(shí)Messenger底層也是AIDL??蛻舳撕头?wù)端通訊,就是普通的AIDL,客戶端實(shí)例化Stub之后,通過Stub的send方法把消息發(fā)到服務(wù)端。服務(wù)端和客戶端通訊:服務(wù)端通過解析message的replyto,獲得客戶端的Stub,然后通過send方法發(fā)送到客戶端。
三.源碼分析
???????從上面實(shí)例使用可以看到,在Service的onBind()方法中通過mMessenger.getBinder()來返回對應(yīng)的IBinder,先看一下Messenger的源碼實(shí)現(xiàn):
a.Messenger.java
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
public IBinder getBinder() {
return mTarget.asBinder();
}
......
......
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
???????從Messenger的源碼可以看到,主要有四個(gè)方法:
???????1.提供給服務(wù)端的構(gòu)造方法,需要傳入Handler實(shí)例,在方法內(nèi)部通過Handler返回IMessenger實(shí)例;
???????2.提供給客戶端的send()方法,發(fā)送message到服務(wù)端;
???????3.提供給服務(wù)端在onBind()返回Binder的方法;
???????4.提供給客戶端在onServiceConnected()內(nèi)部獲取Messenger實(shí)例的方法;
???????Messenger內(nèi)部同時(shí)提供了服務(wù)端和客戶端對應(yīng)的方法,getBinder()是通過mTarget來返回的,mTarget是通過Handler的getIMessenger()來返回的,具體實(shí)現(xiàn)是在Handler內(nèi)部,一起看一下Handler的內(nèi)部對應(yīng)的實(shí)現(xiàn):
b.Handler.java
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
c.IMessenger.aidl
oneway interface IMessenger {
void send(in Message msg);
}
d.IMessenger.java
public interface IMessenger extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IMessenger {
private static final java.lang.String DESCRIPTOR = "android.os.IMessenger";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
........
........
@Override public android.os.IBinder asBinder() {
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code)
..........
case TRANSACTION_send: {
data.enforceInterface(DESCRIPTOR);
android.os.Message _arg0;
if ((0!=data.readInt())) {
_arg0 = android.os.Message.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.send(_arg0);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements android.os.IMessenger {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override public android.os.IBinder asBinder() {
return mRemote;
}
.........
@Override public void send(android.os.Message msg) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((msg!=null)) {
_data.writeInt(1);
msg.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_send, _data, null, android.os.IBinder.FLAG_ONEWAY);
} finally {
_data.recycle();
}
}
}
static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void send(android.os.Message msg) throws android.os.RemoteException;
}
???????從上面可以看到,getIMessenger()返回的是MessengerImpl實(shí)例,而MessengerImpl是繼承了IMessenger.Stub,實(shí)現(xiàn)了send()方法來接收消息,從這里可以看到,用的是跟AIDL相同的處理;
總結(jié)一下
???????服務(wù)端:service的onBind()方法調(diào)用Messenger.getBinder(),最終是通過IMessenger.Stub的asBinder()返回的IBinder;
???????客戶端:onServiceConnected()里面調(diào)用Messenger mService=new Messenger(service)來返回Messenger對象,在構(gòu)造方法內(nèi)部會(huì)先通過IMessenger.Stub.asInterface(target)來創(chuàng)建IMessenger實(shí)例mTarget;
???????交互:客戶端在通過send()發(fā)送消息時(shí),會(huì)通過mTarget的send()方法,經(jīng)過binder驅(qū)動(dòng)處理,會(huì)調(diào)用到IMessenger.Stub的onTransact()方法,最終會(huì)調(diào)用服務(wù)端的MessengerImpl的send()方法,繼而通過Handler來sendMessage(),最后服務(wù)端的Handler來handleMessage();
四.與 AIDL 比較:
???????執(zhí)行 IPC 時(shí),使用 Messenger 要比使用 AIDL 實(shí)現(xiàn)更加簡單,因?yàn)?Messenger 會(huì)將所有服務(wù)調(diào)用排入隊(duì)列,而純粹的 AIDL 接口會(huì)同時(shí)向服務(wù)發(fā)送多個(gè)請求,服務(wù)隨后必須應(yīng)對多線程處理。
???????對于大多數(shù)應(yīng)用,服務(wù)不需要執(zhí)行多線程處理,因此使用 Messenger 可讓服務(wù)一次處理一個(gè)調(diào)用。如果服務(wù)必須執(zhí)行多線程處理,則應(yīng)使用 AIDL 來定義接口。