Android平臺下的WIFI模塊功能
1.開關WIFI
除了在WIFI設置界面可以開關WIFI,還有其他的方法可以設置,要查看這些開關狀態(tài)是否一致。還有就是飛行模式對WIFI開關的影響,由于WIFI開和關都有一個時間過程,而飛行模式的開關瞬間完成,所以有時會出現(xiàn)沖突。
2.開關新可用網(wǎng)絡提醒
新可用網(wǎng)絡的定義是自WIFI模塊開啟后,從未發(fā)現(xiàn)過的,為加密的網(wǎng)絡。只有滿足了新可用網(wǎng)絡的定義,才會有提醒。
3.連接斷開網(wǎng)絡
連接斷開各種不同加密類型的網(wǎng)絡(具體類型下文有詳解)
4.手動添加網(wǎng)絡
需要路由器關閉SIID廣播??墒謩虞斎隨IID,網(wǎng)絡加密類型,密碼。對于OPAL手機來說,路由器隱藏了SSID,手動添加的網(wǎng)絡是無法連接的。
5.搜索網(wǎng)絡
手動點擊搜索按鈕可以搜索網(wǎng)絡,也可以等待WIFI模塊自動搜索網(wǎng)絡。
6.休眠設置
由于WIFI模塊是用電大戶,所有為了省電,Android的WIFI加了一個休眠策略,可以設置永遠不斷開,充電時不斷開和鎖屏時斷開。要測試休眠設置是否有效,可以在路由器上PING手機的IP,PING通就是連接狀態(tài)。OPAL手機的休眠策略屬于完全失效,現(xiàn)在的情況是無論選哪個都會一直保持連接,鎖屏后15分鐘再休眠。
7.設置靜態(tài)IP
Android系統(tǒng)里對IP設置的輸入限制很有問題,我一直認為這是弱智的限制。正常IP的范圍在0-255之間,android對IP輸入的限制是整數(shù)0到整數(shù)255之間,也就是說0000.000200.001.001這樣一個IP都能合法輸入。
熱點加密類型
目前,常見及需要處理的熱點,包括以下3大類:
open——開放型網(wǎng)絡,即無加密,可直接連接
wep——采用wep加密類型的熱點,已過時,不安全,容易被破解,目前使用率已不足10%
wpa/wpa2——目前使用最廣泛,相對最安全,破解難度最大的加密類型
wps(wifiprotectedsetup):是為了進一步增強wpa熱點及簡化連接過程的技術,不屬于加密類型。
android的wifi模塊功能開發(fā)教程
1、獲取WifiManager入口類實例
wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);12
2、打開及關閉wifi
wifiManager.setWifiEnabled(true)1
true表示打開wifi開關,false表示關閉,該方法的返回值僅代表操作是否成功,不代表wifi狀態(tài)的變化;
通過監(jiān)聽廣播WifiManager.WIFI_STATE_CHANGED_ACTION ,來判斷真正的wifi開關變化,該廣播帶有一個int型的值來表示wifi狀態(tài):
int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_DISABLED);
switch (wifistate) {
case WifiManager.WIFI_STATE_DISABLED:
//wifi已關閉
break;
case WifiManager.WIFI_STATE_ENABLED:
//wifi已打開
break;
case WifiManager.WIFI_STATE_ENABLING:
//wifi正在打開
break;
default:
break;
}123456789101112131415
可以看到,該操作其實是一個異步操作,一般耗時在1~3秒之間。
3、周圍熱點掃描
wifiManager.startScan()1
以上方法為開始掃描的接口,其返回值代表操作是否成功,掃描結果通過另外一個接口獲取:
List《ScanResult》 results = wifiManager.getScanResults();1
一般在主動調用startScan之后,大概2秒左右,會收到WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)廣播通知,該廣播包括一個boolean型的額外參數(shù):
boolean isScanned = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, true);1
上面的值表示,掃描結果是否已可用,若可用,則可以使用getScanResults獲取結果,在結果沒有就緒之前,會返回null。
一般系統(tǒng)本身會調用startScan接口,而該操作相對比較耗電,因此在應用中要酌情使用,并不需要頻繁調用。
4、獲取已連接過的熱點
所有已經(jīng)連接過的熱點,都會存在本地一個文件中,一般路徑為/data/misc/wifi/wpa_supplicant.conf(查看需root),而在程序中獲取則通過以下接口:
List《WifiConfiguration》 configurations = wifiManager.getConfiguredNetworks();1
獲取到的WiFiConfiguration對象中,只有ssid和networkId是一定有的,可以用于直接連接該熱點,其他信息如bssid,密鑰等信息基本都是空的。(如何直接連接熱點,下文敘述)
5、獲取當前wifi連接信息
WifiInfo info = wifiManager.getConnectionInfo();1
該對象代表當前已連接的熱點,信息,無連接時返回null;
該對象可獲取包括ssid,bssid,networkId等信息,而ssid是包括了雙引號的,如“CCMC”,在之前的掃描結果ScanResult中,ssid并不帶雙引號。
6、連接指定熱點
連接一個未連接過的熱點時,需3步:
1)創(chuàng)建一個配置:WifiConfiguration
public WifiConfiguration createConfiguration(AccessPoint ap) {
String SSID = ap.getSsid();
WifiConfiguration config = new WifiConfiguration();
config.SSID = “”“ + SSID + ”“”;
String encryptionType = ap.getEncryptionType();
String password = ap.getPassword();
if (encryptionType.contains(“wep”)) {
/**
* special handling according to password length is a must for wep
*/
int i = password.length();
if (((i == 10 || (i == 26) || (i == 58))) && (password.matches(“[0-9A-Fa-f]*”))) {
config.wepKeys[0] = password;
} else {
config.wepKeys[0] = “”“ + password + ”“”;
}
config.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.SHARED);
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.wepTxKeyIndex = 0;
} else if (encryptionType.contains(“wpa”)) {
config.preSharedKey = “”“ + password + ”“”;
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
} else {
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
return config;
}123456789101112131415161718192021222324252627282930
*網(wǎng)上流傳多處創(chuàng)建configuration的代碼,但大都未經(jīng)過驗證,以上代碼已經(jīng)經(jīng)過了線上版本測試,準確可用。
判斷加密類型的方式,可以優(yōu)化,本處僅示例。*
2)生成一個networkId
WifiConfiguration config = createConfiguration(ap);
/**
* networkId is bigger than 0 in most time, 0 in few time and smaller than 0 in no time
*/
int networkId = networkId = wifiManager.addNetwork(config);123456
一般情況下,對一個已經(jīng)連接過的熱點(本地有連接記錄),進行以上操作時,在api21及以上會返回一個小于0的networkId,此時,進行下一步連接是沒有意義的,獲得一個小于0的networkId已經(jīng)表示連接失敗。
3)開始連接
wifiManager.enableNetwork(networkId, true)1
對于已經(jīng)連接過的熱點,通過小項4 中的方式,獲取到該熱點的networkId之后,可直接進行第三步的連接,無需1)2);
若有必要進行12步(如嘗試一個新密碼,因為即使使用了錯誤的密碼連接,系統(tǒng)還是會為本次連接生成一個本地記錄),則必須在一開始,將本地記錄remove掉,remove操作將在下文介紹。
連接結果通過兩個廣播反饋:WifiManager.NETWORK_STATE_CHANGED_ACTION和WifiManager.SUPPLICANT_STATE_CHANGED_ACTION
其中,密碼錯誤的結果通知需通過第二個廣播判斷:
int error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0);
if (WifiManager.ERROR_AUTHENTICATING == error) {
//密碼錯誤,認證失敗
}1234
其他結果均通過第一個廣播接收:
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (null != info) {
NetworkInfo.DetailedState state = info.getDetailedState();
}
}123456
public enum DetailedState {
/** Ready to start data connection setup. */
IDLE,
/** Searching for an available access point. */
SCANNING,
/** Currently setting up data connection. */
CONNECTING,
/** Network link established, performing authentication. */
AUTHENTICATING,
/** Awaiting response from DHCP server in order to assign IP address information. */
OBTAINING_IPADDR,
/** IP traffic should be available. */
CONNECTED,
/** IP traffic is suspended */
SUSPENDED,
/** Currently tearing down data connection. */
DISCONNECTING,
/** IP traffic not available. */
DISCONNECTED,
/** Attempt to connect failed. */
FAILED,
/** Access to this network is blocked. */
BLOCKED,
/** Link has poor connectivity. */
VERIFYING_POOR_LINK,
/** Checking if network is a captive portal */
CAPTIVE_PORTAL_CHECK
}12345678910111213141516171819202122232425262728
7、斷開當前wifi連接
wifiManager.disconnect()1
以上接口返回值代表當前操作是否成功,操作的最終結果,會在兩個廣播中有所反饋:
WifiManager.SUPPLICANT_STATE_CHANGED_ACTION
WifiManager.NETWORK_STATE_CHANGED_ACTION
并且斷開成功的廣播會發(fā)送若干次。
8、遺忘一個已連接過的熱點
boolean isRemoved = wifiManager.removeNetwork(networkId)1
返回值代表操作是否成功,該操作在api21以上的系統(tǒng)中,成功率在10%以下,在api21以下,基本都可以成功;
可以通過反復進行此操作來提高成功率,但效果不大。
評論