本文主要介绍AsyncChannel的使用和内部原理。
一、AsyncChannel概述
AsyncChannel在Wifi的处理机制中被大量使用,但是可惜的是该工具是一个internal的方法,没有开放给第三方应用使用,但是该工具提供的思路很有用,可以被扩展到任意两个Handle间传输数据的通道。
那么AsyncChannel究竟是什么工具呢?他的内部机制又是怎么样呢?我们先来看一下AsyncChannel的官方描述:
* <p>An asynchronous channel between two handlers.</p>
* <p>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.</p>
* <p>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:</p>
* <p>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:</p>
以上是AsyncChannel文件头的描述,从这三段描述中我们可以大致知道AsyncChannel的作用、特点以及用法。
1.1、作用
AsyncChannel在两个Handler间搭建了通道,可以用于消息传输。
1.2、特点
从上面第一段英文描述可以知道AsyncChannel的两个特点:
1、AsyncChannel可以作为Handler之间的通道。2、这两个Handler可以处于同一个进程,也可以不再同一个进程。
1.3、两种工作模式
第二段和第三段英文分别描述了AsyncChannel的两种工作模式:
1、单项通道模式,在该模式下,客户端只能向服务端发起请求,服务端给出回应。2、双向通道模式,在该模式下,客户端和服务端同时连接上AsyncChannel,客户端可以向服务端发送请求,服务端也可以向客户端发送请求。
下面我们分别来介绍这两种模式的使用方法。
二、AsyncChannel通道使用方法
为了进行测试,我搭建了一个Demo程序用于测试相关功能,源码可以这里下载。由于AsyncChannel是internal的工具,因此该Demo必须要在ROM源码环境下编译并具备系统签名。
在这个Demo中,只有三个文件:MainActivity、AsyncChannelClient、AsyncChannelService、AsyncChannelServiceFull四个文件,其作用分别是:MainActivity
----负责界面搭建,里面包含:“初始化客户端和服务端并依次建立单向通道和双向通道”、“初始化客户端和服务端并直接建立双向通道”、“发送异步信息”、“发送同步信息”等四个按钮。
AsyncChannelClient
----作为客户端,向服务端发送请求。
AsyncChannelService
----作为服务端,接受客户端请求。
AsyncChannelServiceFull
----作为服务端,用于接受快速双向通道的请求。
下面来看AsyncChannel的具体使用。
2.1、单向通道建立方法
在这个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,需要做以下几个准备:
1、获取服务端的Messenger对象,该对象其实就是利用服务端的Handler构建的Messenger;
2、创建客户端自己的Handler对象;
3、创建AsyncChannel对象;
4、通过AsyncChannel对象,连接当前的Handler和服务端的Messenger,从而申请连接。
当客户端发送完connect()请求之后,客户端需要做的就是在Handler对象中等待Message消息:
@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()方法向服务端发送消息了。
以上就是单项通道的建立过程,整个过程不需要服务端做任何操作。
2.2、双向通道建立方法