Android IPC之Messenger詳解

一.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 來定義接口。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容