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))

 

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