.簡介

Messenger,顧名思義即為信使,通過它可以在不同進(jìn)程中傳遞Message對象,通過在Message中放入我們需要的入局,就可以輕松實現(xiàn)數(shù)據(jù)的跨進(jìn)程傳遞了。Messenger是一種輕量級的IPC方案,其底層實現(xiàn)是AIDL。

Messenger的使用方法很簡單,它對AIDL進(jìn)程了封裝,并且由于它一次只處理一個請求,因此在服務(wù)端我們不需要考慮同步的問題。

 

2.實現(xiàn)跨進(jìn)程通信

1)服務(wù)端進(jìn)程

首先我們需要在服務(wù)端創(chuàng)建一個Service來處理客戶端的連接請求,同時創(chuàng)建一個Handler并通過它來創(chuàng)建一個Messenger對象。然后在Service的onBind方法中返回這Messenger對象底層的Binder即可。

2)客戶端進(jìn)程

客戶端進(jìn)程中,首先需要綁定服務(wù)端的Service,綁定成功后用服務(wù)端返回的IBinder對象創(chuàng)建一個Messenger,并通過這個Messenger對象向服務(wù)端發(fā)送Message。此外,如果需要服務(wù)端響應(yīng)客戶端,我們就需要像服務(wù)端那樣創(chuàng)建一個Handler并創(chuàng)建一個新的Messenger,并把這個Messenger對象通過Message的replyTo參數(shù)傳遞給服務(wù)器,服務(wù)器就可以通過這個replyTo參數(shù)回應(yīng)客戶端了。

 

     Messenger由于是在AIDL上進(jìn)行了封裝,其使用過程相對比較簡單,下面的示例實現(xiàn)了客戶端發(fā)送消息給服務(wù)端,服務(wù)端會根據(jù)客戶端發(fā)送的消息予以回復(fù)并將回復(fù)的結(jié)果顯示在客戶端上。

3)下面直接貼上client和service的代碼,最后附上運行結(jié)果。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

Client:package com.pignet.messengerdemo2;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity {    private  static  TextView tvMsgFromService;
    Button btnSend;
    EditText etClient;    private Messenger mService;    private Messenger mGetReplyFromService =new Messenger(new MessengerHandler());    private static class MessengerHandler extends Handler{
        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case 1:
                    tvMsgFromService.setText(msg.getData().getString("reply"));                    break;


            }            super.handleMessage(msg);
        }
    }    private ServiceConnection mConnection = new ServiceConnection() {
        @Override        public void onServiceConnected(ComponentName name, IBinder service) {
            mService=new Messenger(service);
        }

        @Override        public void onServiceDisconnected(ComponentName name) {


        }
    };

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnSend= (Button) findViewById(R.id.btn_send);
        etClient= (EditText) findViewById(R.id.et_client);
        tvMsgFromService = (TextView) findViewById(R.id.tv_msg_from_service);
        Intent intent= new Intent(MainActivity.this,MessengerService.class);
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);

        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override            public void onClick(View v) {
                String msgFromClient;
                Message msg = Message.obtain(null,0);
                Bundle data = new Bundle();                if((msgFromClient=String.valueOf(etClient.getText()))==null){
                    Toast.makeText(MainActivity.this,"The Message is null",Toast.LENGTH_SHORT).show();
                }else{
                    data.putString("msg", msgFromClient);
                    msg.setData(data);
                    msg.replyTo= mGetReplyFromService;                    try {
                        mService.send(msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }

            }
        });


    }

    @Override    protected void onDestroy() {
        unbindService(mConnection);        super.onDestroy();
    }
}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

Service:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

package com.pignet.messengerdemo2;import android.app.Service;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.Messenger;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;/**
 * Created by DB on 2017/7/2. */public class MessengerService extends Service {    private static final String TAG="MessengerService";    private static  class  MessengerHandler extends Handler{
        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case 0:
                    Log.i(TAG, "receive msg from client: "+msg.getData().getString("msg"));
                    Messenger mService = msg.replyTo;
                    Message replyMessage = Message.obtain(null,1);
                    Bundle bundle = new Bundle();
                    bundle.putString("reply","您的信息"+msg.getData().getString("msg")+"已收到,稍后會有回復(fù)");
                    replyMessage.setData(bundle);                    try{
                        mService.send(replyMessage);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
            }            super.handleMessage(msg);
        }
    }    private final Messenger mMessenger = new Messenger(new MessengerHandler());
    @Nullable
    @Override    public IBinder onBind(Intent intent) {        return mMessenger.getBinder();
    }
}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

 

這里為了模擬不同應(yīng)用間的跨進(jìn)程通信,將Service類運行在了與Client不同的進(jìn)程中,這樣就可以實現(xiàn)和不同應(yīng)用間通信一樣的效果。

所以我們需要在manifests文件中加入:

<service android:name=".MessengerService"
    android:process=":romote"></service>

運行結(jié)果如下

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

 大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

3.Messenger源碼淺析:

     進(jìn)入到Messenger源碼后,查看它的結(jié)構(gòu)

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

Messenger類有兩個構(gòu)造函數(shù),分別是可以用Handler和IBinder實現(xiàn),這也是我們之前實現(xiàn)跨進(jìn)程中通信中實例化Messenger類中已經(jīng)用到的兩種構(gòu)造函數(shù)。

public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }

因為之前提到過Messenger的底層實現(xiàn)是AIDL,所以這邊我看這個IMessage和那個IBookManager有的類似,點開后發(fā)現(xiàn)確實如此

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

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";        public Stub() {            this.attachInterface(this, DESCRIPTOR);
        }        public static android.os.IMessenger asInterface(...}        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 {...}        private static class Proxy implements android.os.IMessenger {...}    public void send(android.os.Message msg)            throws android.os.RemoteException;
}

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

之前我們?yōu)锽ookManager類定義的方法是一個addBook和getBookList,而這邊我們發(fā)現(xiàn)Messenger對AIDL的封裝中加入的是一個send方法。

那這個方法是在哪里實現(xiàn)的呢。

private final class MessengerImpl extends IMessenger.Stub {        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

它是在Handler類中的MessengerImpl方法中得到實現(xiàn)的,這也就可以解釋我們發(fā)送的message可以在Handler的handleMessage中出現(xiàn)了。

最后我們再回到Messenger類中看看Messenger的另一個重要方法:

    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }

這里我們就可以串聯(lián)起來了,Messenger類通過傳入Handler或是IBinder來獲得IMessenger的實例,然后調(diào)用send方法實際是在遠(yuǎn)程調(diào)用IMessenger的send方法。

這里我們就差不多把Messenger的機(jī)制理清了。

最后附上剛才實現(xiàn)的例子的一個簡圖:

http://www.cnblogs.com/hustzhb/p/7105336.html