本文主要介绍AsyncChannel的使用和内部原理。
AsyncChannel在Wifi的处理机制中被大量使用,但是可惜的是该工具是一个internal的方法,没有开放给第三方应用使用,但是该工具提供的思路很有用,可以被扩展到任意两个Handle间传输数据的通道。
那么AsyncChannel究竟是什么工具呢?他的内部机制又是怎么样呢? * An asynchronous channel between two handlers.
* The handlers maybe in the same process or in another process. There
* are two protocol styles that can be used with an AysncChannel. The
* first is a simple request/reply protocol where the server does
* not need to know which client is issuing the request.
* In a simple request/reply protocol the client/source sends requests to the
* server/destination. And the server uses the replyToMessage methods.
* In this usage model there is no need for the destination to
* use the connect methods. The typical sequence of operations is:
* A second usage model is where the server/destination needs to know
* which client it's connected too. For example the server needs to
* send unsolicited messages back to the client. Or the server keeps
* different state for each client. In this model the server will also
* use the connect methods. The typical sequence of operation is:
以上是AsyncChannel文件头的描述,从这三段描述中我们可以大致知道AsyncChannel的作用、特点以及用法。
AsyncChannel在两个Handler间搭建了通道,可以用于消息传输。
从上面第一段英文描述可以知道AsyncChannel的两个特点:
1、AsyncChannel可以作为Handler之间的通道。2、这两个Handler可以处于同一个进程,也可以不再同一个进程。
第二段和第三段英文分别描述了AsyncChannel的两种工作模式:
1、单项通道模式,在该模式下,客户端只能向服务端发起请求,服务端给出回应。下面我们分别来介绍这两种模式的使用方法。
为了进行测试,我搭建了一个Demo程序用于测试相关功能,源码可以这里下载。由于AsyncChannel是internal的工具,因此该Demo必须要在ROM源码环境下编译并具备系统签名。
在这个Demo中,只有三个文件:MainActivity、AsyncChannelClient、AsyncChannelService、AsyncChannelServiceFull四个文件,其作用分别是:下面来看AsyncChannel的具体使用。
在这个Demo中,当点击“初始化客户端和服务端并依次建立单向通道和双向通道”后,就会先后启动服务端和客户端,当客户端的Server启动(onStartCommand)时,就会与服务端建立单项通道。
我们先来看点击动作的处理: @MainActivity.java
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_service_btn: {
// 启动客户端和服务端
Intent intent = new Intent();
intent.setComponent(new ComponentName(this, AsyncChannelService.class));
startService(intent);
Intent inte = new Intent();
inte.setComponent(new ComponentName(this, AsyncChannelClient.class));
//Action是"Normal"
inte.setAction("Normal");
startService(inte);
break;
}
}
}
然后我们来看客户端的 初始化流程:
@AsyncChannelClient.java
public static AsyncChannel sClientAsyncChannel;
public int onStartCommand(Intent intent, int flags, int startId) {
//创建本地的Handler对象
HandlerThread handlerThread = new HandlerThread("ClientThread");
handlerThread.start();
Handler clientHandler = new ClientHandler(handlerThread.getLooper());
//创建客户端的AsyncChannel
sClientAsyncChannel = new AsyncChannel();
String act = intent.getAction();
//我们发送的Action就是"Normal"
if ("Normal".equals(act)) {
// 建立单向通道,获取服务端的Messenger对象
Messenger serviceMessenger = AsyncChannelService.getServiceMessenger();
//发起连接请求
sClientAsyncChannel.connect(this, clientHandler, serviceMessenger);
} else if ("Fast".equals(act)) {
}
return super.onStartCommand(intent, flags, startId);
}
上面的过程中,通过客户端的getServiceMessenger()方法
拿到服务端的Messenger对象,其过程是:
@AsyncChannelService.java
public static Messenger getServiceMessenger() {
//服务端需要用自己的Handler构建Messenger然后发送给客户端
return new Messenger(mServiceHandler);
}
以上就是客户端所做的全部准备,以及发起创建通道的请求过程。从这个过程中我们看到,作为客户端,如果想要创建与服务端之间的AsyncChannel,需要做以下几个准备:
@AsyncChannelClient.java
public void handleMessage(Message message) {
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
Log.d(tag, "Service half connected");
}
break;
}
}
}
当客户端接收到AsyncChannel.CMD_CHANNEL_HALF_CONNECTED消息后,说明当前的单项通道建立成功。此时的客户端可以通过sAsyncChannel的sendMessage()方法向服务端发送消息了。
以上就是单项通道的建立过程,整个过程不需要服务端做任何操作。
那么如果客户端想要创建双向通道,该如何操作呢?
首先,服务端本身需要初始化Handler,并且如果服务端准备提供双向通道,那么就需要创建自己的AsyncChannel对象。这些工作需要在客户端初始化时完成: @AsyncChannelService.java
public int onStartCommand(Intent intent, int flags, int startId) {
//初始化Handler
HandlerThread handlerThread = new HandlerThread("ServiceThread");
handlerThread.start();
mServiceHandler = new ServiceHandler(handlerThread.getLooper());
//创建AsyncChannel对象
sServiceAsyncChannel = new AsyncChannel();
return super.onStartCommand(intent, flags, startId);
}
其实
双向通道是在单项通道基础上完成的,当客户端与服务端的单项通道创建完成后,也就是
当客户端收到AsyncChannel.CMD_CHANNEL_HALF_CONNECTED之后,可以向AsyncChannel对象发送CMD_CHANNEL_FULL_CONNECTION消息申请建立双向通道。
@AsyncChannelClient.java
public void handleMessage(Message message) {
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
//客户端单项通道建立完成,继续申请双向通道
sClientAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
}
break;
}
}
此时的服务端将会在Handler中接收到如下消息:
@AsyncChannelService.java
public void handleMessage(Message msg) {
switch ((msg.what)) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//服务端接收到双向通道的建立请求
//如果同意客户端建立,则需要服务端向AsyncChannel申请连接请求
sServiceAsyncChannel.connect(AsyncChannelService.this, mServiceHandler, msg.replyTo);
break;
}
}
}
从上面代码看到,当客户端发起双向通道建立请求时,服务端将会收到AysncChannel.CMD_CHANNEL_FULL_CONNECTION的请求,此时的服务端如果同意建立双向通道,则使用自己的AsyncChannel对象将自己的Handler与客户端的Handler连接起来。
以上就是双向通道的建立过程。
上一节中介绍了双向通道的建立方法,其实这是一种“笨方法”,为什么这么说呢?我们来看一下要创建双向通道需要经过哪些步骤:
1、客户端发起connect()请求,申请建立单向通道; @MainActivity.java
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_service_fast_connect_btn: {
Intent intent = new Intent();
intent.setComponent(new ComponentName(this, AsyncChannelServiceFull.class));
startService(intent);
Intent inte = new Intent();
inte.setComponent(new ComponentName(this, AsyncChannelClient.class));
inte.setAction("Fast");
startService(inte);
break;
}
}
}
此时将会先后启动AsyncChannelServiceFull和AsyncChannelClient服务,并且发送的Action为“Fast”。
@AsyncChannelServiceFull.java
public int onStartCommand(Intent intent, int flags, int startId) {
//初始化Handler对象
HandlerThread handlerThread = new HandlerThread("ServiceThread");
handlerThread.start();
mServiceHandler = new ServiceHandler(handlerThread.getLooper());
//创建AsyncChannel对象
sServiceAsyncChannel = new AsyncChannel();
return super.onStartCommand(intent, flags, startId);
}
然后来看AsyncChannelClient的操作:
@AsyncChannelClient.java
public int onStartCommand(Intent intent, int flags, int startId) {
//初始化Handler对象
HandlerThread handlerThread = new HandlerThread("ClientThread");
handlerThread.start();
Handler clientHandler = new ClientHandler(handlerThread.getLooper());
//创建AsyncChannel对象
sClientAsyncChannel = new AsyncChannel();
String act = intent.getAction();
if ("Normal".equals(act)) {
} else if ("Fast".equals(act)) {//此时的Action是"Fast"
// 要求直接双向通道
Handler serviceHandler = AsyncChannelServiceFull.getServiceHandler();
int result = sClientAsyncChannel.fullyConnectSync(this, clientHandler, serviceHandler);
if (AsyncChannel.STATUS_SUCCESSFUL == result) {
Log.d(tag, "client full connected");
}
}
return super.onStartCommand(intent, flags, startId);
}
这与单项通道的建立操作几乎完全一样,唯一不同的地方有三个:
@AsyncChannelServiceFull.java
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//收到双向通道建立请求,如果服务端同意,则需要连接上AsyncChannel,然后恢复STATUS_SUCCESSFUL即可
sServiceAsyncChannel.connect(AsyncChannelServiceFull.this, mServiceHandler, msg.replyTo);
//将建立结果传递给客户端
sServiceAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL);
break;
}
}
}
经过上面服务端的操作,客户端就在fullyConnectSync()返回值中获取到通道建立成功的消息,至此双向通道建立完毕。
以上就是快速双向通道的建立过程。
我们建立通道的最终目的是为了在两个Handler间传输信息,而消息又分为两类:异步消息和同步消息,接下来分别介绍这两种消息的使用方法。
所谓异步消息,就是客户端(或服务端)发送消息之后在Handler中等待回应,而不是立刻拿到消息结果。无论是客户端或者是双向通道中的服务端,都可以通过自己的AsyncChannel对象向对方发送异步消息。
在该Demo中,当点击界面上的“发送异步信息”按钮时,就会在客户端中向服务端发送一个MainActivity.MSG_ASYNC_REQ的请求,接下来在Server端的handleMessage中就能收到该请求,我们在Server收到该请求后,创建一个MSG_SYNC_REPLY的消息,并在其中放入一个字串“ServiceAsyncReply”返回给客户端,接下来客户端就可以在自己的handleMessage中检测到该回应,最终我们在客户端的handleMessage中把该字串打印出来。 @AsyncChannelClient.java
public static void sendMsgToService() {
// 客户端用AsyncChannel给服务端发送MSG_ASYNC_REQ的请求
sClientAsyncChannel.sendMessage(MainActivity.MSG_ASYNC_REQ);
}
接下来就会在服务端的handleMessage中接收到该请求:
@AsyncChannelService.java
public void handleMessage(Message msg) {
switch (msg.what) {
case MainActivity.MSG_ASYNC_REQ: {
//接收到客户端请求
Message reply = msg.obtain();
reply.what = MainActivity.MSG_ASYNC_REPLY;
reply.obj = "ServiceAsyncReply";
try {
//给客户端发送回应,回应的内容中what=MSG_ASYNC_REPLY,obj="ServiceAsyncReply"
msg.replyTo.send(reply);
} catch (RemoteException e) {
}
break;
}
}
然后客户端就会收到MSG_ASYNC_REPLY的回应:
@AsyncChannelClient.java
public void handleMessage(Message message) {
switch (message.what) {
case MainActivity.MSG_ASYNC_REPLY: {
//收到服务端回应,并将服务端放入的字串打印出来,异步消息结束
String msg = (String) message.obj;
Log.d(tag, "get service async reply msg = " + msg);
break;
}
}
}
至此就完成了整个异步消息的调用。
从上面的异步消息看到,无论是客户端发送消息还是服务端返回消息,都是异步的,都需要在发送完毕后被动等待消息结果,而同步消息就是客户端(或服务端)发送消息之后可以直接拿到返回值。
接下来我们通过Demo来演示同步消息的使用方法。 @AsyncChannelClient.java
public static void sendSyncMsgToService() {
Message replyMsg = sClientAsyncChannel.sendMessageSynchronously(MainActivity.MSG_SYNC_REQ);
String msg = (String) replyMsg.obj;
Log.d(tag, "get service sync reply msg = " + msg);
}
从这里的发送过程就可以看出,对于发送端来说,“好像”发送完请求后,立刻得到了消息。当调用AsyncChannel的sendMessageSynchronously()方法后,服务端将会接收到该消息,并进行消息处理:
@AsyncChannelService.java
public void handleMessage(Message msg) {
switch (msg.what) {
case MainActivity.MSG_SYNC_REQ: {
//服务端接收到同步消息请求
Message reply = msg.obtain();
reply.what = MainActivity.MSG_SYNC_REPLY;
reply.obj = "ServiceSyncReply";
//将返回值发送给客户端
sServiceAsyncChannel.replyToMessage(msg, reply);
break;
}
}
}
从服务端消息处理可以看到,服务端接收到MSG_SYNC_REQ请求后,包装了一个reply的Message对象,然后通过服务端的AsyncChannel对象将该消息返回给消息的发送者。然后客户端就收到了服务端的回应。
这就是同步消息的使用方法。
以上通过Demo介绍了AsyncChannel的使用方法,接下来我们介绍AsyncChannel的内部原理。
从前面介绍的通道使用方法来看,第一种双向通道是在单向通道基础上搭建的,我们先来看单项通道的建立过程。
从通道的建立方法可以知道,创建通道需要三个步骤: public class AsyncChannel {}
发现他没有父类,然后看他的构造方法:
@AsyncChannel.java
public AsyncChannel() {
}
构造方法里面也没有任何操作。然后来看connect()方法:
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
connected(srcContext, srcHandler, dstMessenger);
replyHalfConnected(STATUS_SUCCESSFUL);
}
这里面有两个调用,我们先来看第一个connected()方法:
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
//初始化一些变量
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
mDstMessenger = dstMessenger;
}
在这里只是初始化一些变量,我们记得在使用AsyncChannel时,传递了本地的Handler对象和目标的Messenger对象,在这里用本地的Handler对象创建Messenger对象,也就是说,
在AsyncChannel中,拥有了本地和远端的Messenger对象,分别标记mSrcMessenger和mDeathMonitor。
private void replyHalfConnected(int status) {
//准备CMD_CHANNEL_HALF_CONNECTED消息
Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
if (mConnection == null) {
mDeathMonitor = new DeathMonitor();
try {
//监听远端的服务是否死掉
mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);
} catch (RemoteException e) {
mDeathMonitor = null;
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
}
//将CMD_CHANNEL_HALF_CONNECTED发送给本地,也就是客户端
mSrcHandler.sendMessage(msg);
}
在这里主要完成了一件事情,也就是
向客户端发送CMD_CHANNEL_HALF_CONNECTED的消息。
下面介绍双向通道的建立过程。前面的使用方法中我们知道,双向通道的建立需要在客户端收到CMD_CHANNEL_HALF_CONNECTED消息后向AsyncChannel对象发送CMD_CHANNEL_FULL_CONNECTION消息完成的,也就是如下的入口:
public void handleMessage(Message message) {
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
//向AsyncChannel申请双向通道
sClientAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
break;
}
}
}
接下来看AsyncChannel的sendMessage()过程:
@AsyncChannel.java
public void sendMessage(int what) {
Message msg = Message.obtain();
msg.what = what;
sendMessage(msg);
}
public void sendMessage(Message msg) {
msg.replyTo = mSrcMessenger;
try {
//向mDstMessenger发送消息
mDstMessenger.send(msg);
} catch (RemoteException e) {
replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}
从这里看到,AsyncChannel其实只做了一件事情,就是将CMD_CHANNEL_FULL_CONNECTION的消息转发给mDstMessenger,这里的mDstMessenger就是AsyncChannel被创建时初始化的AsyncChannelService中的Handler,然后服务端就收到了CMD_CHANNEL_FULL_CONNECTION的消息。
@AsyncChannelService.java
public void handleMessage(Message msg) {
switch ((msg.what)) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//服务端接收到双向通道的建立请求
//如果同意客户端建立,则需要服务端向AsyncChannel申请连接请求
sServiceAsyncChannel.connect(AsyncChannelService.this, mServiceHandler, msg.replyTo);
break;
}
}
}
然后服务端的AsyncChannel将会进入connect()中处理:
@AsyncChannel.java
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
//做同样的初始化动作
connected(srcContext, srcHandler, dstMessenger);
//然后告诉服务端CMD_CHANNEL_HALF_CONNECTED
replyHalfConnected(STATUS_SUCCESSFUL);
}
这个过程与建立单向通道时客户端所做的动作完全一致,就是初始化服务端AsyncChannel中的mSrcMessenger、mSrcHandler、mDstMessenger等对象,然后向服务端自己发送CMD_CHANNEL_HALF_CONNECTED的消息。
下面我们来看快速双向通道的建立过程。
该过程是通过客户端使用fullyConnectSync()方法来触发的: @AsyncChannel.java
public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
int status = connectSync(srcContext, srcHandler, dstHandler);
if (status == STATUS_SUCCESSFUL) {
Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION);
status = response.arg1;
}
return status;
}
这个方法内部有两个调用,一个connectSync、一个是sendMessageSynchronously,我们先来追踪第一个:
public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
}
public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
connected(srcContext, srcHandler, dstMessenger);
return STATUS_SUCCESSFUL;
}
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
//初始化变量
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
mDstMessenger = dstMessenger;
}
整个过程的结果就是调用connected()方法,这与connect()唯一不同的就是
没有发送CMD_CHANNEL_HALF_CONNECTED消息。
public Message sendMessageSynchronously(int what) {
Message msg = Message.obtain();
msg.what = what;
Message resultMsg = sendMessageSynchronously(msg);
return resultMsg;
}
继续:
public Message sendMessageSynchronously(Message msg) {
Message resultMsg = SyncMessenger.sendMessageSynchronously(mDstMessenger, msg);
return resultMsg;
}
继续:
private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
//创建SyncMessenger对象
SyncMessenger sm = SyncMessenger.obtain();
try {
if (dstMessenger != null && msg != null) {
//将SyncMessenger的Messenger放入消息包中
msg.replyTo = sm.mMessenger;
synchronized (sm.mHandler.mLockObject) {
//将CMD_CHANNEL_FULL_CONNECTION发送给远端的服务
dstMessenger.send(msg);
//阻塞监听唤醒
sm.mHandler.mLockObject.wait();
}
} else {
sm.mHandler.mResultMsg = null;
}
} catch (InterruptedException e) {
sm.mHandler.mResultMsg = null;
} catch (RemoteException e) {
sm.mHandler.mResultMsg = null;
}
Message resultMsg = sm.mHandler.mResultMsg;
sm.recycle();
//将结果返回给客户端
return resultMsg;
}
整个过程的核心在sendMessageSynchronously中处理,该方法中创建了一个SyncMessenger的对象,这是AsyncChannel的内部静态类,
作用就是负责同步传输消息。
msg.replyTo = sm.mMessenger;
然后将消息发送给服务端:
dstMessenger.send(msg);
然后进入阻塞状态:
sm.mHandler.mLockObject.wait();
经过这个操作,服务端就收到CMD_CHANNEL_FULL_CONNECTION的消息,并且该消息的replyTo对象是SyncMessenger,然后我们来看该SyncMessenger的唤醒过程。
@AsyncChannelServiceFull.java
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
//先连接上AsyncChannel
sServiceAsyncChannel.connect(AsyncChannelServiceFull.this, mServiceHandler, msg.replyTo);
//然后给出OK的回应
sServiceAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL);
break;
}
}
}
我们通过上面回应的流程来看如何唤醒SyncMessenger,记得这里最后一个参数是STATUS_SUCCESSFUL:
@AsyncChannel.java
public void replyToMessage(Message srcMsg, int what, int arg1) {
Message msg = Message.obtain();
msg.what = what;
msg.arg1 = arg1;
replyToMessage(srcMsg, msg);
}
继续往下走:
public void replyToMessage(Message srcMsg, Message dstMsg) {
try {
dstMsg.replyTo = mSrcMessenger;
//这里的replyTo记录的就是当初的SyncMessenger的Handler对象
srcMsg.replyTo.send(dstMsg);
} catch (RemoteException e) {
log("TODO: handle replyToMessage RemoteException" + e);
e.printStackTrace();
}
}
到这里我们看到,通过replyToMessage方法,把服务端的消息发送给了Message的replyTo对象,这个对象其实就是我们当初给服务端发送CMD_CHANNEL_FULL_CONNECTION消息时放入的SyncMessenger的Handler对象,因此,此时的SyncMessenger将会收到服务端的消息:
@AsyncChannel.java
private class SyncHandler extends Handler {
public void handleMessage(Message msg) {
mResultMsg = Message.obtain();
mResultMsg.copyFrom(msg);
synchronized(mLockObject) {
//唤醒SyncMessenger
mLockObject.notify();
}
}
}
在这里,我们终于看到将SyncMessenger唤醒的操作,当该Handler被唤醒时,
sendMessageSynchronously()方法就通过wait()方法继续往下执行,然后就将服务端的消息从SyncMessenger的Handler中取出来,最终return给客户端的fullyConnectSync()调用者。
消息派发的机制其实在上一节的通道建立机制中简单介绍过了,因此接下来的解释就比较容易理解了。
我们知道,异步消息的派发是通过AsyncChannel的sendMessage()来完成的:
@AsyncChannelClient.java
public static void sendMsgToService() {
sClientAsyncChannel.sendMessage(MainActivity.MSG_ASYNC_REQ);
}
然后来看AsyncChannel的sendMessage方法:
@AsyncChannel.java
public void sendMessage(int what) {
Message msg = Message.obtain();
msg.what = what;
sendMessage(msg);
}
public void sendMessage(Message msg) {
msg.replyTo = mSrcMessenger;
try {
//向mDstMessenger发送消息
mDstMessenger.send(msg);
} catch (RemoteException e) {
replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}
这个过程与前面4.2节中双向通道建立过程是相同的,其实就是将消息通过AsyncChannel发送给mDstMessenger,也就是远程服务端。
同步消息的处理其实在前面4.3节中快速双向通道建立流程中介绍过,我们来看一下其流程。
发送同步消息是通过sendMessageSynchronously()方法实现的: @AsyncChannelClient.java
public static void sendSyncMsgToService() {
Message replyMsg = sClientAsyncChannel.sendMessageSynchronously(MainActivity.MSG_SYNC_REQ);
String msg = (String) replyMsg.obj;
Log.d(tag, "get service sync reply msg = " + msg);
}
@AsyncChannel.java
public Message sendMessageSynchronously(int what) {
Message msg = Message.obtain();
msg.what = what;
Message resultMsg = sendMessageSynchronously(msg);
return resultMsg;
}
public Message sendMessageSynchronously(Message msg) {
Message resultMsg = SyncMessenger.sendMessageSynchronously(mDstMessenger, msg);
return resultMsg;
}
private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
//创建SyncMessenger对象
SyncMessenger sm = SyncMessenger.obtain();
try {
if (dstMessenger != null && msg != null) {
//将SyncMessenger的Messenger放入消息包中
msg.replyTo = sm.mMessenger;
synchronized (sm.mHandler.mLockObject) {
//将CMD_CHANNEL_FULL_CONNECTION发送给远端的服务
dstMessenger.send(msg);
//阻塞监听唤醒
sm.mHandler.mLockObject.wait();
}
} else {
sm.mHandler.mResultMsg = null;
}
} catch (InterruptedException e) {
sm.mHandler.mResultMsg = null;
} catch (RemoteException e) {
sm.mHandler.mResultMsg = null;
}
Message resultMsg = sm.mHandler.mResultMsg;
sm.recycle();
//将结果返回给客户端
return resultMsg;
}
以上过程是不是很熟悉?没错,这就是建立快速双向通道中最关键的部分,其原理就是在客户端发送消息后,AsyncChannel内部创建一个SyncMessenger对象,等消息发送给服务端之后,SyncMessenger就进入阻塞状态,当服务端回应消息时,SyncMessenger就解除阻塞,然后将结果返回给客户端。