首先,先上一个messenger的工作原理图

GRPC java双向通信 双向通信例子_客户端


从图片可以看出,messenger的通讯是这样的

1,在服务端,我们要构造一个messenger用来接收信息,而这个messenger发送消息的方向是固定的,只能从client发送到service端

2,在客户端,我们要想接收到客户端会传过来的消息,同样也要构造一个messenger来接收消息

下面来看实例,

首先是服务端的代码

package come.example.administrator.myapplication.messager;

import android.app.Service;
import android.content.Intent;
import android.os.*;
import android.support.annotation.Nullable;
import android.util.Log;

public class messageClient extends Service {

    //客户端消息标志
    private static final int MSG_FROM_CLIENT = 0x10001;
    //服务端消息标志
    private static final int MSG_TO_CLIENT = 0x10002;
    //传递消息的参数标志
    private static final String NICK_NAME = "nickName";
    
    //用来接收客户端message的messaHandler,用来给后面的messenger传入的,解析从客户端获取的message
    private static class MessagerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            //获得message实例
            Message msgToClient = Message.obtain(msg);
            switch (msg.what){
                case MSG_FROM_CLIENT:
                    System.out.println("获得来自客户端的信息       "+msg.getData().getString(NICK_NAME));

                    //构造传回客户端的数据bundle
                    Bundle toClicentDate = new Bundle();
                    toClicentDate.putString(NICK_NAME,"这是服务端发出的消息");
                    msgToClient.setData(toClicentDate);
                    msgToClient.what = MSG_TO_CLIENT;

                    //传回Client
                    try {
                        //msg.replyTo在客户端有定义,其实这就是第二个messenger,在messenger中,
                        // 发送消息和接收消息都必须要有一个messenger,而在这个从客户端获取的msg中,其实在客户端已经通过msg.reply=xxx,设置了接收消息的messenger了
                        msg.replyTo.send(msgToClient);
                    } catch (RemoteException e) {

                    }

                    break;
                default:
                    System.out.println("接收到别的信息");
                    super.handleMessage(msg);
            }
        }
    }

    private final Messenger mMessenger =new Messenger((new MessagerHandler()));

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
}




然后是客户端的代码

package come.example.administrator.myapplication.messager;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.*;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import come.example.administrator.myapplication.R;
import come.example.administrator.myapplication.aldl.aldlService;
import come.example.administrator.myapplication.aldl.book;
import come.example.administrator.myapplication.bookManger;

import java.util.ArrayList;

public class MessengerActivity extends AppCompatActivity {
    private static final int MSG_FROM_CLIENT = 0x10001;
    private static final int MSG_TO_CLIENT = 0x10002;

    private static final String NICK_NAME = "nickName";
    boolean isConn=false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);
        Intent intent1 = new Intent(getApplicationContext(), messageClient.class);
        bindService(intent1, mConnection, BIND_AUTO_CREATE);
    }

    public void getClick(View v) throws RemoteException {
        switch (v.getId()){
            case R.id.sendMsg:
                Message msgFromClient = new Message();
                //构造传给客户端的bundle
                Bundle toServiceDate = new Bundle();
                toServiceDate.putString(NICK_NAME,"这里是客户端");

                msgFromClient.what = MSG_FROM_CLIENT;
                msgFromClient.setData(toServiceDate);
                //将自己定义的messenger设置在要发送出去的msg里面,在服务器那边才能通过这个messenger将消息发送回来客户端
                msgFromClient.replyTo = mClient;
                if (isConn)
                {
                    //往服务端发送消息
                    try {
                        mService.send(msgFromClient);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                break;
        }
    }

    //注册一个messenger,监听系统消息
    //mClient ,在前面说过了,messenger的通讯都是这样的,要想发送消息,必须在接收端定义一个messenger,用来接收数据,然后将这个
    //messenger的实例传回给发送端,让发送端调用这个实例的messenger.send方法来发送消息
    private Messenger mClient=new Messenger(new Handler(){
        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(Message msgFromServer)
        {
            switch (msgFromServer.what)
            {
                case MSG_TO_CLIENT:
                    Bundle data = msgFromServer.getData();
                    System.out.println("服务器返回内容    "+data.get(NICK_NAME));
                    break;
            }
            super.handleMessage(msgFromServer);
        }
    });

    private Messenger mService;

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //mService,也就是服务端定义的那个messenger,只有拿到这个服务端的messenger,才能发送消息给服务端
            mService=new Messenger(service);
            System.out.println("链接成功");
            isConn=true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mClient = null;
            isConn=false;
            System.out.println("链接失败");
        }
    };
}


在上面的实例中,我在服务器端先定义一个messenger mMessenger,然后通过service的onBind方法将这个onBind方法返回给客户端activity,客户端那边通过onserviceConnected方法获得这个mMessenger,可以用这个mMessenger的send方法发送消息给服务端

而在activity中,为了让服务端发送消息给自己,同样的,activity作为接收端,要在自己这里定义一个messenger mclient,然后将这个mclient通过在mMessenger发送出去的消息的replyto设置中设置自己实例发送给服务器端,这样服务器端就可以通过接收到的msg.replyto方法消息给客户端

System.out.println("获得来自客户端的信息       "+msg.getData().getString(NICK_NAME));

                    //构造传回客户端的数据bundle
                    Bundle toClicentDate = new Bundle();
                    toClicentDate.putString(NICK_NAME,"这是服务端发出的消息");
                    msgToClient.setData(toClicentDate);
                    msgToClient.what = MSG_TO_CLIENT;

                    //传回Client
                    try {
                        //msg.replyTo在客户端有定义,其实这就是第二个messenger,在messenger中,
                        // 发送消息和接收消息都必须要有一个messenger,而在这个从客户端获取的msg中,其实在客户端已经通过msg.reply=xxx,设置了接收消息的messenger了
                        msg.replyTo.send(msgToClient);
                    } catch (RemoteException e) {

                    }



嗯嗯,这样就能开始服务器和客户端的双向通信了

对了,别忘记服务器端是个service,得在Manifest文件中注册啊