首先,先上一个messenger的工作原理图
从图片可以看出,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文件中注册啊