前言:
AsyncChannel是android系统中的在两个Handler间用于消息传输的机制,这两个Handler可以处于同一个进程,
也可以不再同一个进程。主要用于和网络相关的跨进程通信,例如phone进程和systemserver的ConnectivityService服务,
wifi进程和systemserver的ConnectivityService服务等。
AsyncChannel有两种工作模式:
1、单项通道模式,在该模式下,客户端只能向服务端发起请求,服务端给出回应。
2、双向通道模式,在该模式下,客户端和服务端同时连接上AsyncChannel,客户端可以向服务端发送请求,服务端也
可以向客户端发送请求。
1单通道分析连接过程
单项通道一定有一个是客户端,有一个是服务端,并且客户端可以向服务端发送消息,但是服务端只能响应消息,不能向客户端发送消息。
并且客户端持有AsyncChannel对象,服务端没有。
创建并且连接通道需要4个步骤:
1、获取服务端的Messenger对象(通过服务端的handler对象构造);
2、创建本地的Handler对象;
3、创建AsyncChannel对象,然后调用connect()方法。
4、处理CMD_CHANNEL_HALF_CONNECTED消息。
AsyncChannel是一个很单纯的类,没有继承任何类,定义如下,
public class AsyncChannel {
构造方法如下,
public AsyncChannel() {
}
直接看connecte方法, 调用流程图如下,
Connect方法如下,
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
// We are connected
connected(srcContext, srcHandler, dstMessenger);
// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);
if (DBG) log("connect srcHandler to the dstMessenger X");
}
第一个参数srcContext是客户端的上下文,
第二个参数srcHandler是客户端的Handler对象,
第三个参数dstMessenger是服务端的Messenger对象。
首先调用connected方法初始化变量,
然后调用replyHalfConnected方法发送消息.
connected方法如下,
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connected srcHandler to the dstMessenger E");
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;
if (DBG) log("connected srcHandler to the dstMessenger X");
}
主要是变量的初始化,
变量mSrcContext 指向客户端的上下文,
mSrcHandler指向客户端的Handler对象,
mDstMessenger是指向服务端的Messenger对象,
mSrcMessenger是利用客户端的Handler对象构造的Messenger对象,因此可以算是客户端的Messenger对象。
replyHalfConnected方法如下,
private void replyHalfConnected(int status) {
Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
/*
* Link to death only when bindService isn't used.
*/
if (mConnection == null) {
mDeathMonitor = new DeathMonitor();
try {
mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);
} catch (RemoteException e) {
mDeathMonitor = null;
// Override status to indicate failure
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
}
mSrcHandler.sendMessage(msg);
}
对于客户端和服务端处于同一个进程来说,mConnection为null,因此需要监听服务端是否挂掉。
然后直接利用客户端的mSrcHandler发送CMD_CHANNEL_HALF_CONNECTED消息。
整个连接流程如下,
1、初始化客户端AsyncChannel对象;
2、向客户端发送CMD_CHANNEL_HALF_CONNECTED的消息;
整个过程中没有出现服务端,这是什么情况?
单通道通信是一对多的通信方式(简单的请求与应答方式)
在这种交互方式下,服务器端并不知道请求来自哪个客户端, 通信前双方不需要显示建立连接。
客户端(发送方)将请求发送给服务器(接收方),服务器则通过replayToMessage方法向客户端发送应答消息。
对于跨进程的handler通信,客户端进行连接的时候调用的参数不同的connect方法,
public void connect(Context srcContext, Handler srcHandler, String dstPackageName,
String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
final class ConnectAsync implements Runnable {
Context mSrcCtx;
Handler mSrcHdlr;
String mDstPackageName;
String mDstClassName;
ConnectAsync(Context srcContext, Handler srcHandler, String dstPackageName,
String dstClassName) {
mSrcCtx = srcContext;
mSrcHdlr = srcHandler;
mDstPackageName = dstPackageName;
mDstClassName = dstClassName;
}
@Override
public void run() {
int result = connectSrcHandlerToPackageSync(mSrcCtx, mSrcHdlr, mDstPackageName,
mDstClassName);
replyHalfConnected(result);
}
}
ConnectAsync ca = new ConnectAsync(srcContext, srcHandler, dstPackageName, dstClassName);
new Thread(ca).start();
if (DBG) log("connect srcHandler to dst Package & class X");
}
其中第三个参数和第四个参数分别是服务端的包名和类名。
启动一个线程进行连接, connectSrcHandlerToPackageSync方法如下,
public int connectSrcHandlerToPackageSync(
Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
mConnection = new AsyncChannelConnection();
/* Initialize the source information */
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(srcHandler);
/*
* Initialize destination information to null they will
* be initialized when the AsyncChannelConnection#onServiceConnected
* is called
*/
mDstMessenger = null;
/* Send intent to create the connection */
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(dstPackageName, dstClassName);
boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
if (DBG) log("connect srcHandler to dst Package & class X result=" + result);
return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
}
创建AsyncChannelConnection对象,将服务端和客户端进行绑定,然后才调用replyHalfConnected方法给客户端发送连接的消息。
其他的方法在此就不分析了。