Android之通過用戶名和密碼連接指定wifi熱點(兼容Android9.0和Android10.0和addNetwork(wifiNewConfiguration)返回-1問題)

1 需求

通過用戶名和密碼連接指定wifi熱點,網上的代碼亂七八糟,沒幾個可以用,我這邊整理了下,測試了華爲Android9.0和小米Android9.0和10.0和OPPO Android9.0 都沒問題,直接回調結果就行。

 

 

 

 

 

 

2 問題

在Android10.0手機上

mWifiManager.addNetwork(wifiNewConfiguration);

返回-1

說明不能用這種方式了,

android Q或者更高的版本,這個方法始終返回-1,去看下官網:Android 10 的新方案如下連接:https://developer.android.google.cn/guide/topics/connectivity/wifi-bootstrap
 

 

 

 

 

 

3 代碼實現

   /**
     * 創建 WifiConfiguration,這裏創建的是wpa2加密方式的wifi
     *
     * @param ssid     wifi賬號
     * @param password wifi密碼
     * @return
     */
    public static WifiConfiguration createWifiInfo(String ssid, String password) {
        WifiConfiguration config = new WifiConfiguration();
        config.allowedAuthAlgorithms.clear();
        config.allowedGroupCiphers.clear();
        config.allowedKeyManagement.clear();
        config.allowedPairwiseCiphers.clear();
        config.allowedProtocols.clear();
        config.SSID = "\"" + ssid + "\"";
        config.preSharedKey = "\"" + password + "\"";
        config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        config.status = WifiConfiguration.Status.ENABLED;
        return config;
    }

    public static boolean connectWifiApByName(Context context, String wifiApName, String password) {
        WifiManager mWifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
        WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiApName, password);//使用wpa2的wifi加密方式
        int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
        if (newNetworkId == -1) {
            Log.e(TAG, "操作失敗,需要您到手機wifi列表中取消對設備連接的保存");
            return false;
        }
        Log.i(TAG, "newNetworkId is:" + newNetworkId);
        // 如果wifi權限沒打開(1、先打開wifi,2,使用指定的wifi
        if(!mWifiManager.isWifiEnabled()){
            mWifiManager.setWifiEnabled(true);
        }
        boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
        if (!enableNetwork) {
            Log.e(TAG, "切換到指定wifi失敗");
            return false;
        } else {
            Log.e(TAG, "切換到指定wifi成功");
            return true;
        }
    }


    public interface CallBack {
        void connnectResult(boolean connectResult);
    }

    /**
     * 通過熱點用戶名和密碼連接熱點
     * @param context
     * @param wifiApName
     * @param password
     * @param handler
     */
    public static void connectWifiApByNameAndPwd(Context context, String wifiApName, String password, CallBack callBack) {
        if (context == null || callBack == null) {
            Log.i(TAG, "context == null || callBack == null");
            return;
        }
        WifiManager mWifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
        //Andorid10.以下
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
            WifiConfiguration wifiNewConfiguration = createWifiInfo(wifiApName, password);//使用wpa2的wifi加密方式
            int newNetworkId = mWifiManager.addNetwork(wifiNewConfiguration);
            if (newNetworkId == -1) {
                Log.i(TAG, "操作失敗,需要您到手機wifi列表中取消對設備連接的保存");
                callBack.connnectResult(false);
                return;
            }
            Log.i(TAG, "newNetworkId is:" + newNetworkId);
            // 如果wifi權限沒打開(1、先打開wifi,2,使用指定的wifi
            if (!mWifiManager.isWifiEnabled()) {
                mWifiManager.setWifiEnabled(true);
            }
            boolean enableNetwork = mWifiManager.enableNetwork(newNetworkId, true);
            if (!enableNetwork) {
                Log.i(TAG, "切換到指定wifi失敗");
                callBack.connnectResult(false);
                return;
            }
            Log.i(TAG, "切換到指定wifi成功");
            callBack.connnectResult(true);
        } else {
            boolean isOpenWifi = mWifiManager.isWifiEnabled();
            if (!isOpenWifi) {
                Log.i(TAG, "用戶需要打開wifi開關");
                context.startActivity(new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY));
                callBack.connnectResult(false);
                return;
            }
            NetworkSpecifier specifier =
                    new WifiNetworkSpecifier.Builder()
                            .setSsidPattern(new PatternMatcher(wifiApName, PatternMatcher.PATTERN_PREFIX))
                            .setWpa2Passphrase(password)
                            .build();

            NetworkRequest request =
                    new NetworkRequest.Builder()
                            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                            .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                            .setNetworkSpecifier(specifier)
                            .build();

            ConnectivityManager connectivityManager = (ConnectivityManager)
                    context.getSystemService(Context.CONNECTIVITY_SERVICE);

            ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    // do success processing here..
                    Log.i(TAG, "onAvailable success");
                    Log.i(TAG, "network" + network.toString());
                    callBack.connnectResult(true);
                }

                @Override
                public void onUnavailable() {
                    // do failure processing here..
                    Log.i(TAG, "onUnavailable fail");
                    callBack.connnectResult(false);
                }
            };
            connectivityManager.requestNetwork(request, networkCallback);
        }
    }

connectWifiApByName函數只針對小於等於android 9.0,不能兼容android 10.0,所以connectWifiApByNameAndPwd這個函數支持所有版本類型

調用如下

 WifiApUtil.connectWifiApByNameAndPwd(this, name, password, object : WifiApUtil.CallBack {
                override fun connnectResult(connectResult: Boolean) {
                    Log.i(TAG, "connectResult is:" + connectResult)
                }
            });//

 

 

 

 

 

 

 

4 需要注意的地方

Andorid 10.0連接指定熱點,需要先把wifi需要打開,不然沒反應,沒有回調,我們上面的代碼在Android9.0以下連接指定熱點之前,我們是通過下面的函數打開wifi

 if (!mWifiManager.isWifiEnabled()) {
       mWifiManager.setWifiEnabled(true);
    }

在10.版本,isWifiEnabled()這個函數是生效的,但是setWifiEnabled(true)這個函數是失敗的,沒有效果,我們如果發現沒有打開wifi,我們可以再連接之前進行引導用戶打開,我們可以跳到設置面板提示用戶啓用和禁用 Wi-Fi

startActivity(Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY))

 

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