Android自定义连接指定WiFi&热点开关

Android自定义连接指定WiFi&热点开关

      • 连接WiFi
      • 热点开关

连接WiFi

  • 目的:可通过接受用户输入WiFi SSID、密码、密码类型控制设备连接至该WiFi
  • 步骤:开启WiFi、启动WiFi网络搜索、连接WiFi
  • 具体实现方式:
    (1)启用WIFI:检查设备目前是否已开启WiFi,如果未开启则开启WiFi,如果已开启并且处于已连接状态,则先断开当前连接,随后注册广播监听WiFi状态变化结果。最好不要采用开启WiFi后立即进行WiFi扫描的方式,可能会导致无法获取到WiFi扫描结果的广播
public static void enableWifi(Context context, BroadcastReceiver wifiReceiver) {
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    if (!Objects.requireNonNull(wifiManager).isWifiEnabled()) {
        //WiFi未打开,启用wifi
        wifiManager.setWifiEnabled(true);
    } else {
        //WiFi已打开,检查是否已连接了,如果已连接,先将连接断开。由于WiFi已经打开,可以直接进行WiFi扫描
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        if (wifiInfo != null) {
            wifiManager.disableNetwork(wifiInfo.getNetworkId());
            wifiManager.disconnect();
        }
        wifiManager.scan();
    }
    //注册WiFi扫描结果、WiFi状态变化的广播接收
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    context.registerReceiver(wifiReceiver, intentFilter);
}

(2)创建WiFi扫描结果、WiFi状态变化广播接收

class WifiReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Objects.requireNonNull(action).equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
            //扫描结果广播,查找扫描列表是否存在指定SSID的WiFi,如果存在则进行连接
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            List scanResultList = Objects.requireNonNull(wifiManager).getScanResults();
            for(ScanResult scanResult : scanResultList) {
                if(scanResult.SSID.equals(ssid)) {
                    connectWifi(ssid, password, wifiCipherType, this)
                }
            }
        } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
            //WiFi状态变化广播:如果WiFi已经完成开启,即可进行WiFi扫描
            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
            switch (wifiState) {
                case WifiManager.WIFI_STATE_ENABLED:
                    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                    Objects.requireNonNull(wifiManager).startScan();
                    break;
                case WifiManager.WIFI_STATE_DISABLED:
                    break;
                default:break;
            }
        }
    }
}

(3)连接WiFi:得到扫描结果后即可进行WiFi连接,值得一提的是,如果不进行WiFi扫描,调用getConfiguredNetworks()会返回一个空的列表。得到WiFi配置列表后,判断列表中是否已有该SSID的WiFi配置,如果已有,可以沿用之前的配置(或者进一步判断配置和当前的输入信息是否一致,不一致的话删除旧的配置,使用当前配置)如果完全没有指定SSID的配置,创建对应的配置后再进行连接

public static boolean connectWifi(Context context, String ssid, String password, WifiCipherType wifiCipherType, BroadcastReceiver wifiReceiver) {
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    List wifiConfigurations = Objects.requireNonNull(wifiManager).getConfiguredNetworks();
    for(WifiConfiguration wifiConfiguration : wifiConfigurations) {
        if(wifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
            boolean isWifiEnable = wifiManager.enableNetwork(wifiConfiguration.networkId, true);
            if(isWifiEnable) {
                context.unregisterReceiver(wifiReceiver);
                return true;
            } else {
                context.unregisterReceiver(wifiReceiver);
                return false;
            }
        }
    }
    int netId = wifiManager.addNetwork(createWifiConfiguration(ssid, password, wifiCipherType));
    boolean isWifiEnable = wifiManager.enableNetwork(netId, true);
    if(isWifiEnable) {
        context.unregisterReceiver(wifiReceiver);
        return true;
    }
    context.unregisterReceiver(wifiReceiver);
    return false;
}

(4)创建WIFI配置,注意配置中的SSID以及上述比对过程中的SSID,都需要以""" + ssid + “”"形式的字符串进行使用,否则会出错。关于WiFi配置的创建,已经有很多的代码可参考,这里只列出无加密、WEP、WPA/WPA2加密的配置创建

private static WifiConfiguration createWifiConfiguration(String ssid, String password, WifiCipherType wifiCipherType) {
    WifiConfiguration wifiConfiguration = new WifiConfiguration();
    wifiConfiguration.allowedAuthAlgorithms.clear();
    wifiConfiguration.allowedGroupCiphers.clear();
    wifiConfiguration.allowedKeyManagement.clear();
    wifiConfiguration.allowedPairwiseCiphers.clear();
    wifiConfiguration.allowedProtocols.clear();
    wifiConfiguration.SSID = "\"" + ssid + "\"";
    wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
    if(wifiCipherType == WifiCipherType.WIFI_CIPHER_NOPASS) {
        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfiguration.wepTxKeyIndex = 0;
    } else if(wifiCipherType == WifiCipherType.WIFI_CIPHER_WEP) {
        wifiConfiguration.hiddenSSID = true;
        wifiConfiguration.wepKeys[0]= "\"" + password + "\"";
        wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfiguration.wepTxKeyIndex = 0;
    } else if (wifiCipherType == WifiCipherType.WIFI_CIPHER_WPA_PSK) {
        wifiConfiguration.preSharedKey = "\"" + password + "\"";
        wifiConfiguration.hiddenSSID = false;
        wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
    }
    return wifiConfiguration;
}

通过以上步骤,即可完成WiFi的连接

热点开关

  • 目的:可让用户切换热点开启或者关闭
  • 步骤:判断热点目前状态是开启还是关闭,随后根据用户选择进行切换
  • 具体实现方式:
    (1)判断热点状态:
public static boolean isWifiApEnabled() {
        WifiManager wifiManager = (WifiManager) Utils.getApp().getSystemService(Context.WIFI_SERVICE);
        try {
            Method method = Objects.requireNonNull(wifiManager).getClass().getMethod("isWifiApEnabled");
            method.setAccessible(true);
            return (Boolean) method.invoke(wifiManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

(2)开关热点:此处的方法针对Android7.1,Android7.1的开关热点方案和其他版本都不一样,很容易踩坑,此处的方法参考的是:https://blog.csdn.net/zhang01/article/details/79222057
至于其他版本的热点开关,网上内容较多,就不进行一一赘述

public static boolean setWifiAp(boolean isOpen) {
        ConnectivityManager connectivityManager = (ConnectivityManager) Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        try {
            Field mField = Objects.requireNonNull(connectivityManager).getClass().getDeclaredField("TETHERING_WIFI");
            mField.setAccessible(true);
            int mTETHERING_WIFI = (int)mField.get(connectivityManager);
            Field iConnMgrField = connectivityManager.getClass().getDeclaredField("mService");
            iConnMgrField.setAccessible(true);
            Object iConnMgr = iConnMgrField.get(connectivityManager);
            Class iConnMgrClass = Class.forName(iConnMgr.getClass().getName());
            Method mStartTethering1 = iConnMgrClass.getMethod("startTethering", int.class,ResultReceiver.class,boolean.class);
            mStartTethering1.setAccessible(true);
            mStartTethering1.invoke(iConnMgr, mTETHERING_WIFI, null, isOpen);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

此处需要注意的是,除了WiFi和网络权限外,还需要申请权限:


由于此权限只开放给系统应用,所以需要将应用编译为系统应用,具体方式可查看网上的方案

你可能感兴趣的:(Android)