WiFi模块涉及多个线程、多个进程,它们之间的交互方式主要通过收发消息进行,主要包括:Broadcase、AsyncChannel、StateMachine消息机制
1.Broadcase
广播在wifi模块中使用较为频繁,使用方法也比较简单,通过新建过滤器,并添加相应的action后,进行注册即可监听相应的广播事件。如以下代码:
[WifiSettings.java]
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mSummaryLoader.registerReceiver(this, filter);
此处监听WiFi状态变化、网络状态变化、RSSI变化三个广播。
另外,在WifiManager,WifiServiceImpl,WifiStateMachine等WiFi模块的核心类中也多处用到广播。
2.AsyncChannel
AsyncChannel用于两个Handler之间的通信。它包括Client端和Server端,在通信之前需要建立连接关系(有同步和异步两种方式),WiFi模块中主要使用异步方式。使用步骤如下:
连接阶段:
①Client端创建AsyncChannel对象,并调用其connect方法请求与Server端建立连接,此时为单向通道(ClientServer)
②单向通道连接成功后,Client端的Handler会收到CMD_CHANNEL_HALF_CONNECTED消息,此时通过AsyncChannel的sendMessage()方法向Server端发送一个名为CMD_CHANNEL_FULL_CONNECTION的消息。
③Server端的Handler收到CMD_CHANNEL_FULL_CONNECTION消息后,也创建一个AsyncChannel对象,并调用其connect方法与客户端建立连接,此时双向通道连接完成。
通信阶段:
①Client端通过AsyncChannel的sendMessage方法向Server端发送消息;
②Server端通过replyToMessage向Client端回复消息。
断开连接:
Client端和Server端任意一端都可以调用disconnect函数结束连接。该函数将使Client端和Server端都收到CMD_CHANNEL_DISCONNECTED消息。
WiFi模块中WifiManager和WifiServiceImpl之间的通信主要通过AsyncChannel实现:
[WifiManager](Cilent端)
AsyncChannel = new AsyncChannel();
Handler handler = new ServiceHandler(mLooper);
mAsyncChannel.connect(mContext, handler, messenger);
private class ServiceHandler extends Handler {
//代码省略
private void dispatchMessageToListeners(Message message) {
Object listener = removeListener(message.arg2);
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
} else {
Log.e(TAG, "Failed to set up channel connection");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
mAsyncChannel = null;
}
mConnected.countDown();
break;
case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
// Ignore
break;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Log.e(TAG, "Channel connection lost");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
mAsyncChannel = null;
getLooper().quit();
break;
//代码省略
}
}
}
[WifiServiceImpl](Server端)
private class ClientHandler extends Handler {
//代码省略
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mTrafficPoller.addClient(msg.replyTo);
} else {
Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
}
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
if (DBG) Slog.d(TAG, "Send failed, client connection lost");
} else {
}
mTrafficPoller.removeClient(msg.replyTo);
break;
}
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, this, msg.replyTo);
break;
}
//代码省略
}
}
3.StateMachine消息机制
State设计模式是java设计模式中一种重要的设计模式,其应用也十分广泛。在android中的应用是StateMachine,它和传统的状态机有所区别,使得状态之间有了层级关系。
StateMachine的主要方法属性如下:
-
addState():添加一个状态,可指定其父状态;
-
setInitialState():设置状态机初始状态;
-
start():启动状态机
-
transitionTo():切换到某个状态;
-
obainMessage():获取指定的Message;
-
sendMessage():发送消息给StateMachine,StateMachine的Handler会处理该消息;
-
deferMessage():保留某个消息,等到下一个新状态中处理;
-
quit()/quitNow():停止状态机。
WiFi模块使用了多个StateMachine,最重要的是WifiStateMachine,它共定义了20种状态,通过sendMessage()方法发送消息给StateMachine,StateMachine的Handler调用当前状态的processMessage(Messagemessage)方法进行消息的处理。