Then the previous article continued to analyze the WiFi source code
Android4.4.2 source analysis of WiFi module (i)
In the Onresume method
6> First, call Wifienabler's Resume method to manage switch
Next, register for the broadcast
Getactivity (). Registerreceiver (Mreceiver, Mfilter);
The action of the broadcast listener is as follows
WIFI status Change ACTION mfilter.addaction (wifimanager.wifi_state_changed_action); WiFi scan to nearby available WiFi when the broadcast mfilter.addaction (wifimanager.scan_results_available_action); mfilter.addaction (wifimanager.network_ids_changed_action); Mfilter.addaction (wifimanager.supplicant_state_changed_action); Mfilter.addaction (wifimanager.configured_networks_changed_action); Mfilter.addaction (wifimanager.link_configuration_changed_action); Mfilter.addaction (wifimanager.network_state_changed_action); Mfilter.addaction (wifimanager.rssi_changed_action);
View Wifimanager find each action definition as follows, and after hearing the corresponding broadcast, each processing is as follows
I>
/** * Broadcast Intent action indicating that Wi-Fi has been enabled, disabled, * enabling, disabling, or unknown. One extra provides this, as an int. * Another extra provides the previous state, if available. * * @see #EXTRA_WIFI_STATE * @see #EXTRA_PREVIOUS_WIFI_STATE * /@SdkConstant ( sdkconstanttype.broadcast_intent_action) public static final String wifi_state_changed_action = " Android.net.wifi.WIFI_STATE_CHANGED ";
Wifi_state_changed_action: When WiFi is turned on, off, opening, shutting down, or the status of the WiFi is changed, the system will automatically send the broadcast, the broadcast will be accompanied by two values, one is the int type represents the changed state, It can be obtained through the field extra_wifi_state, and the state (if any) that is before the change of the int type can be obtained by the field Extra_previous_wifi_state
When listening to the broadcast, the following processing occurs: Update the WiFi status (the broadcast is also monitored in wifienbabler to update the switch when the WiFi status changes)
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals (ACTION)) { updatewifistate (Intent.getintextra ( Wifimanager.extra_wifi_state, Wifimanager.wifi_state_unknown));
The Updatewifistate method is as follows
private void Updatewifistate (int state) {Activity activity = getactivity (); if (activity! = NULL) {//Reload menu, this method invokes Oncreateoptionsmenu load Actionbar in activity activity.invalidateo Ptionsmenu (); } switch (state) {case wifimanager.wifi_state_enabled://Open WIFI mscanner.resume ();//From the bottom The method is used to turn on the WiFi scan, and record the number of scans return; "Not", to avoid the "call to Pause" () below case wifimanager.wifi_state_enabling://is opening WIFI Addmessagepreference (r.string.wifi_starting); Break Case wifimanager.wifi_state_disabled://off WiFi//Users can be set in the Wlan--> advanced options when they can be scanned at any time (turn off WiFi can also be scanned), according to the user's choice, Sets the text setoffmessage () on the display interface after the WLAN is turned off; Break } mlastinfo = null; Mlaststate = null; Mscanner.pause ();//Remove Message notification}
Because the updated method involves scanner, where scanner is a custom inner class that inherits from handler, the code is as follows
Private class Scanner extends Handler {private int mretry = 0; void Resume () {if (!hasmessages (0)) {sendemptymessage (0); }} void Forcescan () {removemessages (0); Sendemptymessage (0); } void Pause () {mretry = 0; Removemessages (0); } @Override public void handlemessage (Message message) {if (Mwifimanager.startscan ()) { mretry = 0; } else if (++mretry >= 3) {mretry = 0; Activity activity = getactivity (); if (activity = null) {Toast.maketext (activity, R.string.wifi_fail_to_scan, Toast.length_long). Show (); } return; } sendemptymessagedelayed (0, 10*1000); Send message again after//10s}}
As you can see, the method for scanning available WiFi nearby is Mwifimanager.startscan () the method is visible to the user and can be called directly
Ii>
/** * An access point scan has completed, and results is available from the supplicant. * Call {@link #getScanResults ()} to obtain the results. * /@SdkConstant (sdkconstanttype.broadcast_intent_action) public static final String scan_results_available _action = "Android.net.wifi.SCAN_RESULTS";
The broadcast is sent by the system at the end of the Scan_result_available_action:wifi scan, and the user can listen to the broadcast by calling Wifimanager's Getscanresults method to obtain the scan results
else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals (ACTION) | | WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals (ACTION) | | WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals (ACTION)) { updateaccesspoints ();
when the user scans to WiFi or the WiFi information changes need to go to update the WiFi list, update WiFi list method is updateaccesspoints (), scan load list This feeling is very complex, slowly analysis
First, after the scan is finished, you can get the scanned WiFi list by Getscanresult (), the return value is List<scanresult>, and each wifi you return will carry the following information
What does each field mean?
Bssid:the address of the access point, the AP addresses (string value)
Ssid:the Network Name,wifi name (string value)
Capabilities:describes the Authentication,key Management,and encryption schemes supported by the access point, which describes the authentication of access points , Key management and encryption scheme (string value)
WIFISSID:ASCII encode Ssid,this will replace the SSID when we deprecate it, the ASCII encoding of the SSID, we can use it instead of the SSID when it is not supported(Wifissid value)
Timestamp:timestamp in microseconds (since boot) time this result is last seen, the number of microseconds from the previous change
Level: For the definition of level from the source can be seen, indicating the intensity of the signal, the value of int type,
/** * The detected signal level in DBm, also known as the RSSI. * * <p>use {@link Android.net.wifi.wifimanager#calculatesignallevel} to convert this number into * an Absolute signal level which can is displayed to a user. */public int. level;
for signal strength display, you can use the following code
Mwifilevel.setimagelevel (Wifimanager.calculatesignallevel (mlist.get (position). level,4));
Frequency:the primary MHz frequency (in MHz) of the ' channel over which ' the client is communicating with the access Poin T. How often the client communicates with the access point
We typically show WiFi listings with SSID, level, and capabilities
After scanning to WiFi in Android source, we need to load the list and call the Updateaccesspoints method to update the list after receiving the Scan_result_available_action broadcast. In this method will be based on the WiFi switch status to update the UI, only when the WiFi is turned on to update the list, there are no other cases to repeat, the WiFi is opened by the following code load
private void Updateaccesspoints () {//Safeguard from some delayed event handling if (getactivity () = = NULL ) return; if (isrestrictedandnotpinprotected ()) {addmessagepreference (r.string.wifi_empty_list_user_restricted); Return } final int wifistate = Mwifimanager.getwifistate (); Switch (wifistate) {case wifimanager.wifi_state_enabled://accesspoints is automatically sort Ed with TreeSet. Get to the access point list final collection<accesspoint> accesspoints = constructaccesspoints (); if (!getresources (). Getboolean (r.bool.set_wifi_priority)) {Getpreferencescreen (). RemoveAll (); } if (accesspoints.size () = = 0) {addmessagepreference (r.string.wifi_empty_list_w IFI_ON); } if (!getresources (). Getboolean (r.bool.set_wifi_priority)) {for (accesspoint accesspoint:accesspoints) {<pre name= "code" class= "Java" >//wifiset The root node of the tings XML file is Preferencescreen, so add Preferencegetpreferencescreen () as follows. Addpreference (Accesspoint); }} if (Accesspoints.isempty ()) {addmessagepreference (r.string.wifi_empty_list_wifi_on);} break; Case wifimanager.wifi_state_enabling://If WIFI is in the open state, clear the list ... } }
So how does access point list get done?
Private List<accesspoint> constructaccesspoints () {arraylist<accesspoint> accesspoints = new ArrayLis T<accesspoint> (); /** Lookup table to most quickly update accesspoints by only considering objects with the * correct SSID. Maps SSID, List of accesspoints with the given SSID. *///key for Ssid,value for access point Scanresult multimap<string, accesspoint> apmap = new multimap<string, A Ccesspoint> (); if (Getresources (). Getboolean (r.bool.set_wifi_priority)) {emptycategory (); //getconfigurednetwors can return a list of configurations for a configured network connection that holds information about the connected access point WiFi,//The list returned includes the following fields, which will return NULL when WiFi is off <pre name= "code" class= "java" >/** <ul> * <li>networkId</li> * &L t;li>ssid</li> * <li>BSSID</li> * <li>priority</li> * <LI&G T;allowedprotocols</li> * <li>allowedkeymanagement</li> * <li>allowedAuthAlgorithms</li> * <li>allowedpairwiseciphers</li& Gt * <li>allowedGroupCiphers</li> * </ul> */final list<wificonfiguration> configs = Mwifimanager.getconfigurednetworks (); if (configs! = null) {for (wificonfiguration config:configs) {if (config. SSID = null) {Accesspoint accesspoint = new Accesspoint (getactivity (), config); Accesspoint.update (Mlastinfo, mlaststate); Accesspoints.add (Accesspoint); Apmap.put (Accesspoint.ssid, accesspoint); if (Getresources (). Getboolean (r.bool.set_wifi_priority)) {setapcategory (accesspoint, MCONFIGEDAP); }}} if (Getresources (). Getboolean (r.bool.set_wifi_priority)) { if (MCONFIGEDAP! = null && mconfigEdap.getpreferencecount () = = 0) {getpreferencescreen (). Removepreference (MCONFIGEDAP); }}}//Get WiFi scan results and return to nearby available WiFi, including connected or saved WiFi final list<scanresult> results = Mwifimanager.getscanresults (); if (results! = null) {for (Scanresult result:results) {//Ignore hidden and ad-hoc networks. if (result. SSID = = NULL | | Result. Ssid.length () = = 0 | | Result.capabilities.contains ("[IBSS]")) {continue; } Boolean found = false; For (Accesspoint accessPoint:apMap.getAll (Result). SSID) {if (Accesspoint.update (result)) found = true; } if (!found) {accesspoint accesspoint = new Accesspoint (getactivity (), result); Accesspoints.add (Accesspoint); Apmap.put (ACCEsspoint.ssid, Accesspoint); if (Getresources (). Getboolean (r.bool.set_wifi_priority)) {setapcategory (accesspoint, Munknownap); }}} if (Getresources (). Getboolean (r.bool.set_wifi_priority)) { if (Munknownap!=null && munknownap.getpreferencecount () = = 0) {Getpreferencescree N (). Removepreference (MUNKNOWNAP); }}}//Pre-sort accesspoints to speed preference insertion Collections.sort (accesspoints ); return accesspoints; }
The call to the Mwifimanager.getconfigurenetworks () method gets the list of WiFi connections that have been configured, and the list contains the following values
The protection of the scanned WiFi is determined by judging whether the Scanresult capabilities field contains a corresponding string to determine which protection method
Boolean WPA = Result.capabilities.contains ("Wpa-psk"); Boolean WPA2 = Result.capabilities.contains ("Wpa2-psk")
Iii>
/** * The network IDs of the configured networks could have changed. * /@SdkConstant (sdkconstanttype.broadcast_intent_action) public static final String network_ids_changed_ ACTION = "Android.net.wifi.NETWORK_IDS_CHANGED";
network_ids_changed: The network ID of the configured network may have changed
Iv>
/** * Broadcast Intent action indicating the state of establishing a connection to * An access point have Chan Ged. One extra provides the new * {@link supplicantstate}. Note that the supplicant is a Wi-Fi specific, and is not a generally the most useful thing- UST interested in * The overall state of connectivity. * @see #EXTRA_NEW_STATE * @see #EXTRA_SUPPLICANT_ERROR * * @SdkConstant (sdkconstanttype.broadcast_ intent_action) public static final String supplicant_state_changed_action = " Android.net.wifi.supplicant.STATE_CHANGE ";
Supplicant_state_changed_action: The status of the connection being established has changed and the broadcast will carry a value of two
V>
/** * Broadcast Intent action indicating that the configured networks changed. * This can is as a result of adding/updating/deleting a network. If * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to True the new configuration * can being retreived with the {@l Ink #EXTRA_WIFI_CONFIGURATION} EXTRA. If multiple * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} won't is present. * @hide */public static final String configured_networks_changed_action = "Android.net.wifi.CONFIGURED_ Networks_change ";
Configured_networks_changed_action: The system sends the broadcast when the network is added, updated, or deleted in the WiFi list, but the broadcast is hidden from the user and cannot be called
Vi>
/** * Broadcast Intent action indicating the state of Wi-Fi connectivity * has changed. One extra provides the new state * in the form of a {@link Android.net.NetworkInfo} object. If the new * is CONNECTED, additional extras may provide the BSSID and wifiinfo of * The access point. * As a {@code String}. * @see #EXTRA_NETWORK_INFO * @see #EXTRA_BSSID * @see #EXTRA_WIFI_INFO * /@SdkConstant ( sdkconstanttype.broadcast_intent_action) public static final String network_state_changed_action = " Android.net.wifi.STATE_CHANGE ";
Network_state_changed_action:wifi connection changes when the system will send the broadcast, through the field extra_network_info can get the status of the WiFi connection, if the status is connected, there will be an additional two fields, Field Extra_bssid can get to the Wifiinfo instance of the connected WiFi bssid, field extra_wifi_info can get information to the connected WiFi
Vii>
/** * The RSSI (signal strength) has changed. * @see #EXTRA_NEW_RSSI * /@SdkConstant (sdkconstanttype.broadcast_intent_action) public static final String rssi_changed_action = "Android.net.wifi.RSSI_CHANGED";
Wifi_rssi_changed: When the WiFi signal strength changes, the system will send the broadcast, through the field Extra_new_rssi can get the changed WiFi signal strength, of course, also need to update the WiFi list
Android4.4.2 source analysis of the WiFi module (ii)