[TOC]

文章参考:https://blog.csdn.net/SuperBigLw/article/details/53158164

一、概述

Messenger实现IPC通信,底层也是使用了AIDL方式。和AIDL方式不同的是, Messenger方式是利用Handler形式处理,因此,它是线程安全的,这也表示它不支持并发处理;而AIDL方式是非线程安全的,支持并发处理,因此,我们使用,AIDL方式时需要保证代码的线程安全。
大部分情况下, 我们应用中不需要并发处理。 因此, 我们通常只需要使用Messenger方式。
思想:在进程A中创建一个Message,将这个Message对象通过Messenger.send(message)方法传递到进程B(当然, Message对象本身是无法被传递到进程B的, send(message)方法会使用一个Parcel对象对Message对象编集,再将Parcel对象传递到进程B中,然后解编集,得到一个和进程,A中Message对象内容一样的对象) ,再把Message对象加入到进程B的消息队列里, Handler会去处理它。

二、具体步骤,双向通信的实现

1.首先创建一个Service服务,并实现一个 Handler,由其接收来自客户端的每个调用的回调
(这个是接收时的代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
System.out.println(msg.getData().getString("info"));

break;
default:
super.handleMessage(msg);
}
}
}

(实现双向通信的代码,接收后发送给客户端)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
System.out.println(msg.getData().getString("info"));
//实现双向通讯
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null, MSG_SAY_HELLO);
for(int i = 0;i<20;i++){
try {
Thread.sleep(500);
Bundle bundle = new Bundle();
bundle.putString("reply", "嗯嗯,我已经收到你的第"+i+"条信息,稍后回复你。");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

break;
default:
super.handleMessage(msg);
}
}
}

2.Handler 用于创建 Messenger 对象(对 Handler 的引用)

1
final Messenger mMessenger = new Messenger(new IncomingHandler());

3.Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端

1
2
3
4
5
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}

4.上述完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;

/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
System.out.println(msg.getData().getString("info"));
//实现双向通讯
Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null, MSG_SAY_HELLO);
for(int i = 0;i<20;i++){
try {
Thread.sleep(500);
Bundle bundle = new Bundle();
bundle.putString("reply", "嗯嗯,我已经收到你的第"+i+"条信息,稍后回复你。");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

break;
default:
super.handleMessage(msg);
}
}
}

/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());

/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}

5.客户端使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用后者将 Message 对象发送给服务
(1)定义一个Messenger对象,Messenger mService = null;并在绑定成功后实例化

1
2
3
4
5
6
7
8
9
10

public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}

(2)声明一个Handler用来处理服务端的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessengerService.MSG_SAY_HELLO:
System.out.println("receive from Service:" + msg.getData().get("reply"));
TextView textView = new TextView(getApplicationContext());
textView.setTextColor(Color.BLACK);
textView.setText("receive from Service:" + msg.getData().get("reply"));
linearLayout.addView(textView);
break;
default:
super.handleMessage(msg);
}
}
}

(3)声明一个Messenger对象

1
private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());

(4)创建一个Message对象并用Messenger发送给服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
Bundle bundle = new Bundle();
bundle.putString("info","呵呵哒");
msg.setData(bundle);
msg.replyTo = mGetReplyMessenger;
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}

并用msg.replyTo得到Messenger实例