标签:
接着上一篇继续对WiFi源码的分析
onResume方法中
6>,首先是调用WiFiEnabler的resume方法对switch进行管理
接下来注册广播
getActivity().registerReceiver(mReceiver, mFilter);
广播监听的action如下
//wifi状态改变的action mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //WiFi扫描到附近可用WiFi时的广播 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);
i>
/** * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, * enabling, disabling, or unknown. One extra provides this state 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状态(在WiFiEnbabler中也监听了该广播,用于当WiFi状态改变时对switch进行更新)
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
updateWifiState方法如下
private void updateWifiState(int state) { Activity activity = getActivity(); if (activity != null) { //重新加载菜单 ,该方法会调用activity中的onCreateOptionsMenu加载actionbar activity.invalidateOptionsMenu(); } switch (state) { case WifiManager.WIFI_STATE_ENABLED://打开WiFi mScanner.resume();//从下面的方法中可以看到,该方法是用于开启WiFi的扫描,并记录扫描次数 return; // not break, to avoid the call to pause() below case WifiManager.WIFI_STATE_ENABLING://正在打开WiFi addMessagePreference(R.string.wifi_starting); break; case WifiManager.WIFI_STATE_DISABLED://关闭WiFi //用户可以在wlan-->高级选项中去设置时是否随时都可以扫描(关闭WiFi后也可以扫描),根据用户的选择, //设置在关闭WLAN后显示界面上的文本 setOffMessage(); break; } mLastInfo = null; mLastState = null; mScanner.pause();//移除message通知 }
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);//10s后再次发送message } }
ii>
/** * An access point scan has completed, and results are 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";SCAN_RESULT_AVAILABLE_ACTION:WiFi扫描结束时系统会发送该广播,用户可以监听该广播通过调用WifiManager的getScanResults方法来获取到扫描结果
else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) || WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) || WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) { updateAccessPoints();
首先在扫描结束后可以通过getScanResult()获取到扫描后的WiFi列表,返回值为List<ScanResult>,所返回的每个WiFi会携带如下信息
各字段分别代表什么含义呢?
BSSID:The address of the access point,接入点地址(String值)
SSID:The network name,WiFi名字(String值)
capabilities:Describes the authentication,key management,and encryption schemes supported by the access point,描述接入点的身份验证,密钥管理和加密方案(String值)
wifiSsid:ASCII encode SSID,This will replace SSID when we deprecate it ,SSID的ASCII码编码,当不支持它时我们可以用它来代替ssid(WifiSsid值)
timestamp:timestamp in microseconds (since boot)when this result was last seen,距离上一次的更改的微秒数
level:对于level的定义从源码中可以看到,表示信号的强度,属于int型数值,
/** * 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 be displayed to a user. */ public int level;
mWifiLevel.setImageLevel(WifiManager.calculateSignalLevel(mList.get(position).level,4));
frequency:The primary 20 MHz frequency (in MHz) of the channel over which the client is communicating with the access point.客户端与接入点通信的频率
我们一般显示WiFi列表用到的是SSID、level和capabilities
Android源码中扫描到WiFi后就需要去加载列表,在接收到SCAN_RESULT_AVAILABLE_ACTION广播后调用updateAccessPoints方法进行更新列表,在该方法中会根据WiFi的开关状态来对UI进行更新,只有在WiFi开启时 才会去更新列表,这里不再对其他情况进行赘述,在WiFi开启时会通过如下代码加载
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 are automatically sorted with TreeSet. //获取到接入点列表 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_wifi_on); } if (!getResources().getBoolean(R.bool.set_wifi_priority)) { for (AccessPoint accessPoint : accessPoints) { <pre name="code" class="java"> //WiFisettings的xml文件的根节点为preferencescreen,所以通过如下方法添加 preferencegetPreferenceScreen().addPreference(accessPoint); } } if (accessPoints.isEmpty()){ addMessagePreference(R.string.wifi_empty_list_wifi_on); } break; case WifiManager.WIFI_STATE_ENABLING://如果WiFi处于正在打开的状态,则清除列表 。。。。。。。。。 } }
那么接入点列表的获取是如何进行的呢?
private List<AccessPoint> constructAccessPoints() { ArrayList<AccessPoint> accessPoints = new ArrayList<AccessPoint>(); /** Lookup table to more quickly update AccessPoints by only considering objects with the * correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */ //key为ssid,value为接入点ScanResult Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>(); if (getResources().getBoolean(R.bool.set_wifi_priority)) { emptyCategory(); } //getConfiguredNetwors可以返回一个配置列表,获取到配置好的网络连接,该列表存放了关于已经连接过的接入点WiFi的信息, //返回的列表中包括如下字段,当WiFi 关闭时会返回null <pre name="code" class="java"> /** <ul> * <li>networkId</li> * <li>SSID</li> * <li>BSSID</li> * <li>priority</li> * <li>allowedProtocols</li> * <li>allowedKeyManagement</li> * <li>allowedAuthAlgorithms</li> * <li>allowedPairwiseCiphers</li> * <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); } } } //获取到WiFi扫描结果,返回附近可用WiFi,包括已经连接的或者已经保存的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){ getPreferenceScreen().removePreference(mUnKnownAP); } } } // Pre-sort accessPoints to speed preference insertion Collections.sort(accessPoints); return accessPoints; }
调用mWifiManager.getConfigureNetworks()方法获取到的是已经配置过连接过的WiFi列表,列表包含下列值
对于扫描到的WiFi的保护方式通过判断scanresult的capabilities字段是否包含对应的string来判断属于何种保护方式
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:所配置的网络的网络ID可能已经改变
iv>
/** * Broadcast intent action indicating that the state of establishing a connection to * an access point has changed.One extra provides the new * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and * is not generally the most useful thing to look at if you are just 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:正在建立的连接状态已经改变,该广播会携带两个值
v>
/** * Broadcast intent action indicating that the configured networks changed. * This can be as a result of adding/updating/deleting a network. If * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present. * @hide */ public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
vi>
/** * Broadcast intent action indicating that 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 * state 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连接发生改变时系统会发送该广播,通过字段EXTRA_NETWORK_INFO可以获取到WiFi连接的状态,如果是已连接的状态,则会有额外的两个字段,字段EXTRA_BSSID可以获取到所连接的WiFi的bssid,字段EXTRA_WIFI_INFO可以获取到所连接的WiFi的信息获取到wifiinfo实例
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";
标签:
原文地址:http://blog.csdn.net/zrf1335348191/article/details/51351895