关于WiFi模块(连接流程介绍)


(一)基本类的调用

Android 已经帮助我们做好了一些可以直接调用的类
打开andriod.net.wifi 我们可以看到Android 提供的几个类。
在看这一部分之前,最好能用一下PC 上的wifi,这样对我们的理解会很有帮助!
这里列了很多,但是大致可以分为四个主要的类ScanResult,wifiConfiguration,WifiInfo,WifiManager


(1)ScanResult,主要是通过wifi 硬件的扫描来获取一些周边的wifi 热点的信息。
在我们进行wifi 搜索的时候,一般会搜到这些信息,首先是接入点名字、接入点信息的强弱、还有接入点使用的安全模式,是WPA、WPE。

BSSID 接入点的地址,这里主要是指小范围几个无线设备相连接所获取的地址,比如说两台笔记本通过无线网卡进行连接,双方的无线网卡分配的地址
SSID 网络的名字,当我们搜索一个网络时,就是靠这个来区分每个不同的网络接入点
Capabilities 网络接入的性能,这里主要是来判断网络的加密方式等
Frequency 频率,每一个频道交互的MHz 数
Level 等级,主要来判断网络连接的优先数。
这里只提供了一个方法,就是将获得信息编程字符串toString()

(2)wifiConfiguration 在我们连通一个wifi 接入点的时候,需要获取到的一些信息。

六个子类
WifiConfiguration.AuthAlgorthm 用来判断加密方法
WifiConfiguration.GroupCipher 获取使用GroupCipher 的方法来进行加密
WifiConfiguration.KeyMgmt 获取使用KeyMgmt 进行
WifiConfiguration.PairwiseCipher 获取使用WPA 方式的加密
WifiConfiguration.Protocol 获取使用哪一种协议进行加密
wifiConfiguration.Status 获取当前网络的状态


(3)WifiInfo 在我们的wifi 已经连通了以后,可以通过这个类获得一些已经连通的wifi 连接的信息
getBSSID() 获取BSSID
getDetailedStateOf() 获取客户端的连通性,
getHiddenSSID() 获得SSID 是否被隐藏
getIpAddress() 获取IP 地址
getLinkSpeed() 获得连接的速度
getMacAddress() 获得Mac 地址
getRssi() 获得802.11n 网络的信号
getSSID() 获得SSID
getSupplicanState() 返回具体客户端状态的信息


(4)wifiManager 这个不用说,就是用来管理我们的wifi 连接。
这里来说相对复杂,里面的内容比较多,但是通过字面意思,我们还是可以获得很多相关的信息。这
个类里面预先定义了许多常量,我们可以直接使用,不用再次创建。

addNetwork(WifiConfiguration config) 通过获取到的网络的链接状态信息,来添加网络

calculateSignalLevel(int rssi , int numLevels) 计算信号的等级
compareSignalLevel(int rssiA, int rssiB) 对比连接A 和连接B
createWifiLock(int lockType, String tag) 创建一个wifi 锁,锁定当前的wifi 连接
disableNetwork(int netId) 让一个网络连接失效
disconnect() 断开连接
enableNetwork(int netId, Boolean disableOthers) 连接一个连接
getConfiguredNetworks() 获取网络连接的状态
getConnectionInfo() 获取当前连接的信息
getDhcpInfo() 获取DHCP 的信息
getScanResulats() 获取扫描测试的结果
getWifiState() 获取一个wifi 接入点是否有效
isWifiEnabled() 判断一个wifi 连接是否有效
pingSupplicant() ping 一个连接,判断是否能连通
ressociate() 即便连接没有准备好,也要连通
reconnect() 如果连接准备好了,连通
removeNetwork() 移除某一个网络
saveConfiguration() 保留一个配置信息

setWifiEnabled() 让一个连接有效
startScan() 开始扫描
updateNetwork(WifiConfiguration config) 更新一个网络连接的信息
此外wifiManaer 还提供了一个内部的子类,也就是wifiManagerLock
WifiManagerLock 的作用是这样的,在普通的状态下,如果我们的wifi 的状态处于闲置,那么网络的连通,将会暂时中断。但是如果我们把当前的网络状态锁上,那么wifi 连通将会保持在一定状态,当然接触锁定之后,就会恢复常态。


(二)wifi流程

(1)初始化

在 SystemServer 启动的时候,会生成一个 ConnectivityService 的实例,

              try {
                    Log.i(TAG, "Starting Connectivity Service.");
                    ServiceManager.addService(Context.CONNECTIVITY_SERVICE, new ConnectivityService(context));
              } catch (Throwable e) {
                    Log.e(TAG, "Failure starting Connectivity Service", e);
              }


ConnectivityService 的构造函数会创建 WifiService,

if (DBG) {

 Log.v(TAG, "Starting Wifi Service.");

}

          mWifiStateTracker = new WifiStateTracker(context, handler);
          WifiService wifiService = new WifiService(context, mWifiStateTracker);
          ServiceManager.addService(Context.WIFI_SERVICE, wifi
Service);

WifiStateTracker 会创建 WifiMonitor 接收来自底层的事件,WifiService 和 WifiMonitor 是整个模块的核心。WifiService 负责启动关闭 wpa_supplicant、启动关闭 WifiMonitor 监视线程和把命令下发给 wpa_supplicant,而 WifiMonitor 则负责从 wpa_supplicant 接收事件通知。

(2)连接AP

1. 使能 WIFI

WirelessSettings 在初始化的时候配置了由 WifiEnabler 来处理 Wifi 按钮,

     private void initToggles() {

          mWifiEnabler = new WifiEnabler(this,  (WifiManager) getSystemService(WIFI_SERVICE),(CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI));

当用户按下 Wifi 按钮后,  Android 会调用 WifiEnabler 的 onPreferenceChange,    再由 WifiEnabler调用 WifiManager 的 setWifiEnabled 接口函数,通过 AIDL,实际调用的是 WifiService 的setWifiEnabled 函数,WifiService 接着向自身发送一条 MESSAGE_ENABLE_WIFI 消息,在处理该消息的代码中做真正的使能工作:首先装载 WIFI 内核模块(该模块的位置硬编码为"/system/lib/modules/wlan.ko" ), 然 后 启 动 wpa_supplicant ( 配 置 文 件 硬 编 码 为"/data/misc/wifi/wpa_supplicant.conf") 再通过 WifiStateTracker 来启动 WifiMonitor 中的监视线程。

     private boolean setWifiEnabledBlocking(boolean enable) {

          final  int eventualWifiState =  enable ? WIFI_STATE_ENABLED :WIFI_STATE_DISABLED;

updateWifiState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING);

          if (enable) {

              if (!WifiNative.loadDriver()) {

                       Log.e(TAG, "Failed to load Wi-Fi driver.");

             updateWifiState(WIFI_STATE_UNKNOWN);

                       return false;
                }

           if (!WifiNative.startSupplicant()) {

                       WifiNative.unloadDriver();

             Log.e(TAG, "Failed to start supplicant daemon.");

                       updateWifiState(WIFI_STATE_UNKNOWN);

                       return false; 

                }
                mWifiStateTracker.startEventLoop();
          }
             // Success!
             persistWifiEnabled(enable);
             updateWifiState(eventualWifiState);
             return true;
      }

当使能成功后,会广播发送 WIFI_STATE_CHANGED_ACTION 这个 Intent 通知外界 WIFI已 经 成 功 使 能 了 。 WifiEnabler 创 建 的 时 候 就 会 向 Android 注 册 接 收WIFI_STATE_CHANGED_ACTION,因此它会收到该 Intent,从而开始扫描。

          private void handleWifiStateChanged(int wifiState) {
             if (wifiState == WIFI_STATE_ENABLED) {

                  loadConfiguredAccessPoints();

                  attemptScan();

             }

2. 查找 AP

扫描的入口函数是 WifiService 的 startScan,它其实也就是往 wpa_supplicant 发送 SCAN 命令。

static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz)

{

      jboolean result;

      // Ignore any error from setting the scan mode.

      // The scan will still work.

      (void)doBooleanCommand("DRIVER SCAN-ACTIVE", "OK");

      result = doBooleanCommand("SCAN", "OK");

      (void)doBooleanCommand("DRIVER SCAN-PASSIVE", "OK");

      return result;

}

当 wpa_supplicant 处理完 SCAN 命令后,它会向控制通道发送事件通知扫描完成,从而wifi_wait_for_event 函数会接收到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来出来这个事件,

             void handleEvent(int event, String remainder) {
                        case SCAN_RESULTS:
                             mWifiStateTracker.notifyScanResultsAvailable();
                             break;

WifiStateTracker 则接着广播发送 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent

                  case EVENT_SCAN_RESULTS_AVAILABLE:
                        mContext.sendBroadcast(new 
Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

WifiLayer 注册了接收 SCAN_RESULTS_AVAILABLE_ACTION 这个 Intent,所以它的相关处理函数 handleScanResultsAvailable 会被调用,在该函数中,先会去拿到 SCAN 的结果(最终是往 wpa_supplicant 发送 SCAN_RESULT 命令并读取返回值来实现的)                             ,

                List<ScanResult> list = mWifiManager.getScanResults();

对每一个扫描返回的 AP,WifiLayer 会调用 WifiSettings 的 onAccessPointSetChanged 函数,从而最终把该 AP 加到 GUI 显示列表中。

     public void onAccessPointSetChanged(AccessPointState ap, boolean added) {

          AccessPointPreference pref = mAps.get(ap);

          if (added) {

                if (pref == null) {

                      pref = new AccessPointPreference(this, ap);

                      mAps.put(ap, pref);

                } else {

                      pref.setEnabled(true);

                }

                mApCategory.addPreference(pref);

          }

     }


3. 配置 AP 参数

当用户在 WifiSettings 界面上选择了一个 AP 后,会显示配置 AP 参数的一个对话框,

     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {

          if (preference instanceof AccessPointPreference) {

                AccessPointState  state = ((AccessPointPreference) preference).getAccessPointState();

                showAccessPointDialog(state, AccessPointDialog.MODE_INFO);

          }

     }


4. 连接

当用户在 AcessPointDialog 中选择好加密方式和输入密钥之后,再点击连接按钮,Android就会去连接这个 AP。

     private void handleConnect() {

          String password = getEnteredPassword();

          if (!TextUtils.isEmpty(password)) {

                mState.setPassword(password);

          }

          mWifiLayer.connectToNetwork(mState);

     }

WifiLayer 会先检测这个 AP 是不是之前被配置过,这个是通过向 wpa_supplicant 发送LIST_NETWORK 命令并且比较返回值来实现的,

          // Need WifiConfiguration for the AP

          WifiConfiguration config = findConfiguredNetwork(state);

如果 wpa_supplicant 没有这个 AP 的配置信息, 则会向 wpa_supplicant 发送 ADD_NETWORK命令来添加该 AP,

          if (config == null) {

                // Connecting for the first time, need to create it

                config = addConfiguration(state, ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE);

          }

ADD_NETWORK 命 令 会 返 回 一 个 ID , WifiLayer 再 用 这 个 返 回 的 ID 作 为 参 数 向wpa_supplicant 发送 ENABLE_NETWORK 命令,从而让 wpa_supplicant 去连接该 AP。

          // Make sure that network is enabled, and disable others

          mReenableApsOnNetworkStateChange = true;

          if (!mWifiManager.enableNetwork(state.networkId, true)) {

                Log.e(TAG, "Could not enable network ID " + state.networkId);

                error(R.string.error_connecting);

                return false;

          }


5. 配置 IP 地址

当 wpa_supplicant 成功连接上 AP 之后,它会向控制通道发送事件通知连接上 AP 了,从而wifi_wait_for_event 函数会接收到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来出来这个事件,

          void handleEvent(int event, String remainder) {

                     case CONNECTED:

                           handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);

                           break;

WifiMonitor 再调用 WifiStateTracker 的 notifyStateChange,WifiStateTracker 则接着会往自身发送 EVENT_DHCP_START 消息来启动 DHCP 去获取 IP 地址,

     private void handleConnectedState() {

          setPollTimer();

          mLastSignalLevel = -1;

          if (!mHaveIPAddress && !mObtainingIPAddress) {

                mObtainingIPAddress = true;

                mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();

          }

     }

然后再广播发送 NETWORK_STATE_CHANGED_ACTION 这个 Intent

                case EVENT_NETWORK_STATE_CHANGED:

                     if (result.state != DetailedState.DISCONNECTED || !mDisconnectPending) {

                           intent   = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);

                           intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);

                          if (result.BSSID != null)

                                intent.putExtra(WifiManager.EXTRA_BSSID, result.BSSID);

                                mContext.sendStickyBroadcast(intent);

                     }

                     break;

WifiLayer 注册了接收 NETWORK_STATE_CHANGED_ACTION 这个 Intent,所以它的相关处理函数 handleNetworkStateChanged 会被调用,当 DHCP 拿到 IP 地址之后,会再发送 EVENT_DHCP_SUCCEEDED 消息,

     private class DhcpHandler extends Handler {

          public void handleMessage(Message msg) {

                switch (msg.what) {

                     case EVENT_DHCP_START:

                          if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo)) {

                                event = EVENT_DHCP_SUCCEEDED;

                                                      }

WifiLayer 处 理 EVENT_DHCP_SUCCEEDED 消 息 , 会 再 次 广 播 发 送NETWORK_STATE_CHANGED_ACTION 这个 Intent,这次带上完整的 IP 地址信息。

                case EVENT_DHCP_SUCCEEDED:

                     mWifiInfo.setIpAddress(mDhcpInfo.ipAddress);

                     setDetailedState(DetailedState.CONNECTED);

                     intent  =  new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);

                     intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);

                     mContext.sendStickyBroadcast(intent);

                     break;

至此为止,整个连接过程完成

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AndroidWiFi连接流程图主要包括以下步骤: 1. 打开WiFi:用户进入设置界面,打开设备的WiFi开关,使设备开始搜索可用的WiFi网络。 2. 搜索和扫描:Android设备开始搜索周围的WiFi网络,扫描到的网络信息将会显示在WiFi设置列表中,包括网络名称(SSID)、信号强度等。 3. 用户选择网络:用户根据列表中显示的网络信息,选择要连接WiFi网络。 4. 请求连接Android设备通过向选择的WiFi网络发送请求连接的请求,包括认证信息和其他必要的参数。 5. 连接认证:WiFi网络收到连接请求后,会进行身份验证,包括密码验证、MAC地址过滤等。如果认证通过,网络将发送认可的连接响应。 6. IP地址获取:一旦连接成功,Android设备将向WiFi网络请求分配一个IP地址,以便在网络上进行通信。 7. 地址分配:WiFi网络会为设备分配一个合法的IP地址,并将该信息通过DHCP(动态主机配置协议)返回给设备。 8. 连接成功:设备接收到IP地址和其他网络配置信息后,与WiFi网络建立连接成功。 9. 数据传输:现在,设备可以通过WiFi网络进行数据传输,包括浏览互联网、收发电子邮件等。 10. 断开连接:当用户关闭设备的WiFi开关或者设备离开WiFi网络的范围时,设备会与WiFi网络断开连接。 总的来说,AndroidWiFi连接流程图涵盖了搜索、选择、连接认证、IP地址获取、数据传输等多个环节,确保设备可以顺利地连接和使用WiFi网络。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值