1. 程式人生 > >Android 6.0 關於WiFi的改變

Android 6.0 關於WiFi的改變

你也可以檢視我的其他同類文章,也會讓你有一定的收貨!

最近發現在安卓6.0的機子上,無法切換到指定WiFi,與其說是安卓6.0的問題,不如說是自己以前的程式碼不符合規範。

問題:

連線到指定WiFi,我之前使用的程式碼如下:

// 新增一個網路並連線
    public void addNetwork(WifiConfiguration wcg) {
        int wcgID = mWifiManager.addNetwork(wcg);
        boolean b = mWifiManager.enableNetwork(wcgID , true);
     }

在Android 6.0 中WiFiManager addNetwork(WifiConfiguration config),新增同一ssid時會返回-1,這個時候你再將這個-1 (NetWorkId)傳進enableNetwork(-1,true),肯定連不上WiFi。

分析原因

在官方的文章這篇文章翻譯的不錯)中,介紹了關於安卓6.0中有關WiFi的改變。如下:

Wi-Fi and Networking Changes

This release introduces the following behavior changes to the Wi-Fi and networking APIs.

  • Your apps can now change the state of WifiConfiguration objects only if you created these objects. You are not permitted to modify or delete WifiConfiguration objects created by the user or by other apps.

  • Previously, if an app forced the device to connect to a specific Wi-Fi network by using enableNetwork() with the disableAllOthers=true setting, the device disconnected from other networks such as cellular data. In This release, the device no longer disconnects from such other networks. If your app’s targetSdkVersion is “20” or lower, it is pinned to the selected Wi-Fi network. If your app’s targetSdkVersion is “21” or higher, use the multinetwork APIs (such as openConnection(), bindSocket(), and the new bindProcessToNetwork() method) to ensure that its network traffic is sent on the selected network.

解釋:
原因就是第一條,在掃描WiFi列表時,系統會自動建立曾經連線成功過的WiFi的WifiConfiguration ,使用addNetwork()新增這個WiFi時,就是改變了系統建立的WifiConfiguration物件,所以addNetwork()會返回-1。

在addNetwork的原始碼中發現:

 public int addNetwork(WifiConfiguration config) {
        if (config == null) {
            return -1;
        }
        //這裡改變了WifiConfiguration
        config.networkId = -1;
        return addOrUpdateNetwork(config);
    }

在Android 5.1系統中,即使已經存在指定SSID的WifiConfiguration物件,再次使用addNetwork()新增相同的網路,新增成功而且返回的ID和新增之前的一樣,我猜測是返回了系統的WifiConfiguration物件,雖然有改變WifiConfiguration物件

但是手動在WLAN設定中,刪除網路A,再次連線網路A,發現網路A的WifiConfiguration的ID,不一樣了,如果addNetwork()中不是返回WifiConfiguration物件,那麼ID應該不一樣。

解決方法:

下面只是一個大概思路,程式碼並不完整

private void Wificonnect() {
        // 連線到外網
        WifiConfiguration mWifiConfiguration;
        WifiManager mWifiManager = new WifiAdmin(this);
        String SSID = wifiName.replace("+", " ");
        String password = wifiPwd;
        //檢測指定SSID的WifiConfiguration 是否存在
        WifiConfiguration tempConfig = IsExsits(SSID);
        if (tempConfig == null) {
            //建立一個新的WifiConfiguration ,CreateWifiInfo()需要自己實現
            mWifiConfiguration = CreateWifiInfo(SSID, password, 3);
            int wcgID = mWifiManager.addNetwork(mWifiConfiguration );
            boolean b = mWifiManager.enableNetwork(wcgID, true);
        } else {
        //發現指定WiFi,並且這個WiFi以前連線成功過
            mWifiConfiguration = tempConfig;
            boolean b = mWifiManager.enableNetwork(mWifiConfiguration .networkId, true);
        }

}

//判斷曾經連線過得WiFi中是否存在指定SSID的WifiConfiguration 
public WifiConfiguration IsExsits(String SSID) {
        List<WifiConfiguration> existingConfigs = mWifiManager
                .getConfiguredNetworks();
        for (WifiConfiguration existingConfig : existingConfigs) {
            if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                return existingConfig;
            }
        }
        return null;
}

關注我的公眾號,輕鬆瞭解和學習更多技術
這裡寫圖片描述