android AsyncChannel机制 --- 单通道连接

前言:

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方法给客户端发送连接的消息。

其他的方法在此就不分析了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值