Android WIFI開發之廣播監聽

在 WIFI 網絡開發過程中,容易對網絡變化的系統廣播和不同廣播對應的網絡狀態區分不清楚,所以對常用的系統網絡廣播Intent Action和網絡狀態含義做了整理,希望能夠加強記憶並且幫助到大家理解何時應該監聽哪種系統廣播。

一、 WifiManager.WIFI_STATE_CHANGED_ACTION
解釋: WIFI 開關(是否可用)狀態廣播
狀態相關類: WifiManager

狀態如下:

  • WIFI_STATE_DISABLED: WIFI功能已經被關閉
  • WIFI_STATE_DISABLING: WIFI功能關閉中,處於此狀態WIFI不可以用
  • WIFI_STATE_ENABLED: WIFI功能已經被打開
  • WIFI_STATE_ENABLING: WIFI功能正在打開中,處於此狀態WIFI可用
  • WIFI_STATE_UNKNOWN: WIFI功能狀態不可知

狀態獲取代碼:

Intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,0):WIFI當前開關狀態;
Intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE,0):WIFI開關前一個狀態;

二、 WifiManager.NETWORK_STATE_CHANGED_ACTION
解釋: 網絡狀態變化廣播
狀態相關類: NetworkInfo

1)通用狀態(State):

  • CONNECTING: 正在連接網絡;
  • CONNECTED: 網絡連接成功;
  • SUSPENDED: 網絡暫停;
  • DISCONNECTING: 正在斷開連接;
  • DISCONNECTED: 連接已斷開;
  • UNKNOWN: 未知狀態;

2)詳細狀態(DetailedState):

  • IDLE: 準備開始數據連接設置;
  • SCANNING:正在搜索可用網絡;
  • CONNECTING: 正在建立數據連接;
  • AUTHENTICATING: 網絡連接建立,執行身份認證;
  • OBTAINING_IPADDR: 等待DHCP服務器的相應以分配IP地址信息;
  • CONNECTED: 此時IP流量應該是可用的;
  • SUSPENDED: IP流量暫停
  • DISCONNECTING: 當前正在斷開數據連接;
  • DISCONNECTED: 網絡連接已斷開,IP流量不可用;
  • FAILED:嘗試連接失敗;
  • BLOCKED: 禁止訪問此網絡;
  • VERIFYING_POOR_LINK: 鏈接連接不良;
  • CAPTIVE_PORTAL_CHECK: 檢查網絡是否是強制網絡門戶;

通用狀態和詳細狀態在源碼中有對應關係,源代碼如下:

static {
        stateMap.put(DetailedState.IDLE, State.DISCONNECTED);
        stateMap.put(DetailedState.SCANNING, State.DISCONNECTED);
        stateMap.put(DetailedState.CONNECTING, State.CONNECTING);
        stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING);
        stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING);
        stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING);
        stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING);
        stateMap.put(DetailedState.CONNECTED, State.CONNECTED);
        stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED);
        stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
        stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
        stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
        stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
    }

對應關係圖表爲:

詳細狀態名稱 通用狀態名稱
IDLE、SCANNING DISCONNECTED
CONNECTING、AUTHENTICATING、OBTAINING_IPADDR、VERIFYING_POOR_LINK、CAPTIVE_PORTAL_CHECK CONNECTING
CONNECTED CONNECTED
SUSPENDED SUSPENDED
DISCONNECTING DISCONNECTING
DISCONNECTED、FAILED、BLOCKED DISCONNECTED

因此,只有在CONNECTED時網絡IP纔可用,網絡纔算是連接完成。

注: DHCP : 動態主機設置協議,是局域網的網絡協議,用於內部網和網絡服務商自動分配IP地址。
狀態獲取代碼:

intent.getParcelableExtra<Parcelable>(WifiManager.EXTRA_NETWORK_INFO): 獲取NetworkInfo#State狀態

三、 WifiManager.SUPPLICANT_STATE_CHANGED_ACTION
解釋: 建立與Access Point的連接狀態變化廣播
狀態標註類: SupplicantState

狀態如下:

  • DISCONNECTED: 客戶端未連接AP,但是正在搜索一個AP,如連接丟失時觸發;
  • INTERFACE_DISABLED: 禁用網絡接口時進入此狀態,wpa_supplication拒絕任何使用無線的操作;
  • INACTIVE: WIFI配置中沒有啓用的網絡時進入此狀態,同時沒有和任何網絡嘗試連接,需要外部交互來建立連接;
  • SCANNING: 正在掃描網絡;
  • AUTHENTICATING: 發現合適網絡,嘗試與此網絡進行認證時進入此狀態,與網絡驅動相關;
  • ASSOCIATING: 嘗試與SSID對應的AP進行關聯,與網絡驅動相關;
  • ASSOCIATED: 當網絡驅動已經返回與AP的關聯成功時進入此狀態,如果使用的是IEEE 802.1X模式,會等到起身份認證成功後進入此狀態;
  • FOUR_WAY_HANDSHAKE: 當WPA/WPA2 四次握手啓動時進入此狀態,如果是WPA-PSK情況下,關聯成功後接收到第一個EAPOL-Key幀時會直接進入此狀態。在WPA-EAP的情況下,會完成認證後進入;
  • GROUP_HANDSHAKE:四次握手完成,當請求者開始接收消失時,進入此狀態;
  • COMPLETED:所有認證已經完成進入狀態,此時可能沒有分配任何IP,需要發送DHCP請求來獲取地址;
  • DORMANT:用戶明確發出中斷指令時進入狀態;
  • UNINITIALIZED: 沒有連接wpa_supplicant,是一個僞狀態;
  • INVALID: 僞狀態,一般不會出現;

注: AP代表Access Point,網絡熱點;WPA、WPA-EAP、IEEE 802.1x等名詞請查看博客 Android WiFi 之 認證標準、密鑰管理、加密方案

狀態獲取代碼:

intent.getParcelableExtra<Parcelable>(WifiManager.EXTRA_NEW_STATE) : 獲取SupplicantState狀態

SupplicantState和NetworkInfo#DetailedState同樣存在對應關係,源代碼如下:

 static {
        stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
        stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
        stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
        stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
        stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
        stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
        stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
        stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
        stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
        stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
        stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
        stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
        stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
    }

對應關係圖表如下:

SupplicantState狀態 NetworkInfo#DetailedState狀態
DISCONNECTED、INTERFACE_DISABLED、DORMANT DISCONNECTED
INACTIVE、UNINITIALIZED IDLE
SCANNING SCANNING
AUTHENTICATING、ASSOCIATING、ASSOCIATED CONNECTING
FOUR_WAY_HANDSHAKE、GROUP_HANDSHAKE AUTHENTICATING
COMPLETED OBTAINING_IPADDR
INVALID FAILED

由此可以看出,SupplicantState狀態更多的是NetworkInfo#DetailedState的過程狀態,對整個網絡連接做了更詳細的劃分,但是沒有任何狀態表面Access Point已經可用。

通過SupplicantState獲取NetworkInfo#DetailedState,調用系統API WifiInfo.getDetailedStateOf(SupplicantState suppState)即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章