异步通道机制
概述
AsyncChannel用来连接两个Handler之间的异步消息处理的通道,它的实现核心是Messenger。 因此它不仅支持进程内的消息传递,还支持多进程间的消息传递。 AsyncChannel是Framework内部使用的一种通信机制,并没有作为API给应用程序使用。
两种模式
- AsyncChannel的核心实现是基于跨进程的Handler-Message机制,可参见跨进程消息处理机制。
-
AsyncChannel提供了两种模式的通信方法,称为半连接(
Half Connection
)和全连接(Full Connection
)。
模式 | 客户端调用方法 | 服务端调用方法 | 描述 | 备注 |
---|---|---|---|---|
半连接 | connect、sendMessage | replyToMessage | 客户端发送请求给服务端,服务端不需要知道客户端的存在,只需要回复客户端消息。 | |
全连接 | connect、sendMessage | connected、sendMessage | 服务端在客户端发送请求后,主动再次连接客户端,并通过四次握手方式完成全连接的建立。 |
AsyncChannel命令标识
- 在AsyncChannel通信协议中,使用一组命令标识描述当前连接建立的过程。
-
所有命令都以BASE为基数:
int BASE = Protocol.BASE_SYSTEM_ASYNC_CHANNEL;
。
命令标识 | Message.arg1 | Message.obj | Message.replyTo | 描述 |
---|---|---|---|---|
CMD_CHANNEL_HALF_CONNECTED | 0 => STATUS_SUCCESSFUL, 1 => STATUS_BINDING_UNSUCCESSFUL | AsyncChannel对象 | 目标Messenger | |
CMD_CHANNEL_FULL_CONNECTION | X | X | 源Messenger | |
CMD_CHANNEL_FULLY_CONNECTED | 0 => 接受连接, other => 拒绝连接 | X | X | |
CMD_CHANNEL_DISCONNECT | X | X | 断开连接的Messenger | |
CMD_CHANNEL_DISCONNECTED | 0 => STATUS_SUCCESSFUL, 1 => STATUS_BINDING_UNSUCCESSFUL, 2 => STATUS_SEND_UNSUCCESSFUL | AsyncChannel对象 | 断开连接的Messenger |
AsyncChannel状态标识
- AsyncChannel连接是否成功根据一组状态标识判断。
状态标识 | 值 | 描述 |
---|---|---|
STATUS_SUCCESSFUL | 0 | 连接成功 |
STATUS_BINDING_UNSUCCESSFUL | 1 | 绑定连接时出错 |
STATUS_SEND_UNSUCCESSFUL | 2 | 发送消息时出错 |
STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED | 3 | 当连接一个已存在的连接时被拒绝 |
AsyncChannel如何工作
- AsyncChannel的工作方式主要分为以下几个阶段:发起连接请求、确认连接请求、发送消息、回复消息、断开连接等。对于以上每一个步骤,AsyncChannel类都提供了相应的方法,并考虑到不同的对象作为参数。
发起连接请求
方法名称 | 描述 | 备注 |
---|---|---|
connectSrcHandlerToPackageSync(Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) | 连接一个Handler到一个Class | |
connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) | 同步连接一个Handler到一个Messenger | |
connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) | 同步连接一个Handler到另一个Handler | |
fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) | 两个Handler之间做全连接 | |
connect(Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) | 连接一个Handler到一个Class | |
connect(Context srcContext, Handler srcHandler, Class<?> klass) | 连接一个Handler到一个Class | |
connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) | 连接一个Handler到一个Messenger | |
connect(Context srcContext, Handler srcHandler, Handler dstHandler) | 连接两个Handler | |
connect(AsyncService srcAsyncService, Messenger dstMessenger) | 连接AsyncService和Messenger |
确认连接请求
方法名称 | 描述 | 备注 |
---|---|---|
connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) | 连接Handler和Messenger,该方法通常在做全连接时,由Server调用回复给客户端 |
发送消息
方法名称 | 描述 | 备注 |
---|---|---|
sendMessage(Message msg) | 向目标Handler发送消息 | |
sendMessage(int what) | 向目标Handler发送消息 | |
sendMessage(int what, int arg1) | 向目标Handler发送消息 | |
sendMessage(int what, int arg1, int arg2) | 向目标Handler发送消息 | |
sendMessage(int what, int arg1, int arg2, Object obj) | 向目标Handler发送消息 | |
sendMessage(int what, Object obj) | 向目标Handler发送消息 |
回复消息
方法名称 | 描述 | 备注 |
---|---|---|
replyToMessage(Message srcMsg, Message dstMsg) | 回复dstMsg给srcMsg | |
replyToMessage(Message srcMsg, int what) | 回复消息给srcMsg | |
replyToMessage(Message srcMsg, int what, int arg1) | 回复消息给srcMsg | |
replyToMessage(Message srcMsg, int what, int arg1, int arg2) | 回复消息给srcMsg | |
replyToMessage(Message srcMsg, int what, int arg1, int arg2, Object obj) | 回复消息给srcMsg | |
replyToMessage(Message srcMsg, int what, Object obj) | 回复消息给srcMsg |
断开连接
方法名称 | 描述 | 备注 |
---|---|---|
disconnected() | 当Handler接收到CMD_CHANNEL_DISCONNECTED消息时调用 | |
disconnect() | 主动断开连接 |
示例代码
客户端发送请求
- 以WifiService为例,该类包含一个连接通道WifiStateMachineHandler,它在初始化时与WifiStateMachine建立连接。
-
当连接建立以后,WifiService可利用这个AsyncChannel与WifiStateMachine之间进行消息通信,并且在断开连接后还会自动重连。
private class WifiStateMachineHandler extends Handler { private AsyncChannel mWsmChannel; WifiStateMachineHandler(android.os.Looper looper) { super(looper); // 创建AsyncChannel对象 mWsmChannel = new AsyncChannel(); // 与WifiStateMachine的Handler建立连接 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); } @Override public void handleMessage(Message msg) { switch (msg.what) { // 建立半连接半状态 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { mWifiStateMachineChannel = mWsmChannel; } else { mWifiStateMachineChannel = null; } break; } // 连接断开状态 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { mWifiStateMachineChannel = null; // 重新与Server建立连接 mWsmChannel.connect(mContext, this, mWifiStateMachine.getHandler()); break; } default: { break; } } } } WifiStateMachineHandler mWifiStateMachineHandler;
服务端接收请求
- WifiService同样包含一个等待连接的服务端AsyncServiceHandler,当有客户端连接时,它会记录每个客户端对象,并在断开连接时移除。
-
当客户端连接建立以后,可通过AsyncChannel发送
WifiManager.CMD*
消息给该AsyncServiceHandler进行消息处理。private class AsyncServiceHandler extends Handler { AsyncServiceHandler(android.os.Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { mClients.add((AsyncChannel) msg.obj); } else { } break; } case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { } else { } mClients.remove((AsyncChannel) msg.obj); break; } case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { AsyncChannel ac = new AsyncChannel(); ac.connect(mContext, this, msg.replyTo); break; } case WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL: { mEnableTrafficStatsPoll = (msg.arg1 == 1); mTrafficStatsPollToken++; if (mEnableTrafficStatsPoll) { notifyOnDataActivity(); sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); } break; } case WifiManager.CMD_TRAFFIC_STATS_POLL: { if (msg.arg1 == mTrafficStatsPollToken) { notifyOnDataActivity(); sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); } break; } case WifiManager.CMD_CONNECT_NETWORK: { if (msg.obj != null) { mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj); } else { mWifiStateMachine.connectNetwork(msg.arg1); } break; } case WifiManager.CMD_SAVE_NETWORK: { mWifiStateMachine.saveNetwork((WifiConfiguration)msg.obj); break; } case WifiManager.CMD_FORGET_NETWORK: { mWifiStateMachine.forgetNetwork(msg.arg1); break; } case WifiManager.CMD_START_WPS: { mWifiStateMachine.startWps(msg.replyTo, (WpsInfo)msg.obj); break; } case WifiManager.CMD_DISABLE_NETWORK: { mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2); break; } default: { break; } } } } private AsyncServiceHandler mAsyncServiceHandler;