Android11 wifi密码类型判断和总结

news/2024/11/12 6:51:44/

Android11 wifi密码类型判断和总结

本文主要介绍wifi密码类型的判断,这个对不同类型wifi连接分析有一定帮助。

文章目录

  • Android11 wifi密码类型判断和总结
    • 一、wifi 普通类型正常连接代码
    • 三、wifi获取基本信息获取
      • 1、获取wifi基本信息的api:
      • 2、梳理一下 WifiConfiguration 和 ScanResult :
      • 3、梳理一下wifi常用信息
    • 二、wifi密码加密类型判断
      • 1、ScanResult 中的判断和暴露的方法
      • 2、WifiConfiguration 中的判断
      • 3、SettingLib 中 AccessionPoint 中的判断
      • 4、ScanResultUtil 中的判断
      • 5、总结一下 ScanResult 、 WifiConfiguration 、 AccessionPoint 这三个类对象的联系和区别
        • (1) 各自特点和联系
        • (2)区别
    • 三、自定义wifi连接网络对加密类型封装
      • 1、思路
      • 2、WifiBean
        • (1)WifiBean对象的定义
      • 3、WifiUtils
    • 四、关于其他wifi加密类型相关知识
      • 1、Android 所有加密类型详解
      • 2、如果有同名的wifi 如何处理?
      • 3、 wifi 的 networkId
      • 4、wifi、热点信息保存文件位置:
      • 4、wifi 设置密码类型的不同合成 WifiConfiguration 写法
      • 5、wifi 已保存/已连接的情况修改数据
      • 6、wifi 加密类型判断错误会导致连接失败
    • 五、Android 加密类型使用总结
      • 1、Android wifi 的连接都是必现要基于WifiConfiguration对象
      • 2、wifi 扫描到的对象是 ScanResult ,已保存的wifi 对象是 WifiConfiguration
      • 3、WiFi常用的数据基本都在 ScanResult 中,都是要经过一定的转换才能得到
      • 4、wifi的开发要总结一个自己的封装类
      • 5、wifi 加密类型的判断主要是针对不同类型设置不同参数合成 WifiConfiguration

一、wifi 普通类型正常连接代码

//wifi连接代码public static void connect(Context context, WifiConfiguration config) {WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);//第一个参数是wifi配置信息,包含:WiFi 名称,wifi 加密类型,wifi 密码等基本信息//第二个参数是连接回调,只有加密类型不匹配会报这个错误,密码错误或者其他异常情况这个回调是没用的wifiManager.connect(config, null);}//创建wifi连接的基本信息public WifiConfiguration createWifiInfo(String SSID, String Password, int TYPE) {//创建配置信息对象WifiConfiguration config = new WifiConfiguration();//名称必须要加双引号config.SSID = "\"" + SSID + "\"";//密码类型设置和密码设置if (TYPE == 0) { //无密码的情况config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);}if (TYPE == 1) { //加密类型为:wepconfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);//密码设置if ((length == 10 || length == 26 || length == 58)&& password.matches("[0-9A-Fa-f]*")) {mBean.mConfig.wepKeys[0] = password;} else {mBean.mConfig.wepKeys[0] = '"' + password + '"';}}if (TYPE == 2) { //加密类型为:wpa/wap2,目前最常用,普通wifi和手机热点,也有特殊手机比如红米可以发出wap3热点config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);if (password.matches("[0-9A-Fa-f]{64}")) {config.preSharedKey = password;} else {config.preSharedKey = '"' + password + '"';}}if (TYPE == 4) { //wpa3config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);if (mPasswordView.length() != 0) {String password = mPasswordView.getText().toString();config.preSharedKey = '"' + password + '"';}}return config;}//普通Activity界面连接wifi网络代码private connectWifi() {//连接名称myHost,密码为12345678 的热点网络connect(this, createWifiInfo("myHost", "12345678", 2))}

从上面wifi连接的代码看,主要的逻辑都是在判断wifi密码类型上,所以wifi密码类型是很关键的。

无论是自己手动添加连接的wifi,还是点击扫描到的wifi,其实都是需要最后合成 WifiConfiguration 进行连接。

系统应用一直是以config进行连接的,普通应用很多先通过config获取networkId,再通过networkId,进行连接,
如果处理不当,一个同一个wifi 会有多个networkId,比如多次连接异常,但是未进行移除networkId就会有这个问题。

三、wifi获取基本信息获取

手动添加的情况,是我们比较了解该wifi加密类型的情况,直接输入对应参数进行连接就可以了。

如果是隐藏的wifi,也只能手动进行连接了!

下面主要介绍能扫描到的wifi列表获取。

1、获取wifi基本信息的api:

    // 扫描出的wifi列表private List<ScanResult> mWifiList = mWifiManager.getScanResults();// 设备保存的wifi列表private List<WifiConfiguration> mWifiConfigurations = mWifiManager.getConfiguredNetworks();

设备最开始的时候每个wifi条目都是一个 ScanResult 对象,
连接的时候我们创建了 WifiConfiguration ,并且把一下配置信息加进去,就成为我们后面连接wifi的配置对象。

2、梳理一下 WifiConfiguration 和 ScanResult :

WifiConfiguration 对象 = ScanResult 部分信息(名称) + 我们添加的信息(密码和加密类型)

WifiConfiguration 都是我们曾经连接过的信息,不管成功失败都有可能被保存,
但是应用中基本是进行了remove/forget操作,有些原生应用也没做,新手机上基本是判断未连接成功进行移除的!

3、梳理一下wifi常用信息

wifi 的基本信息开发者基本用下面这些就可以了:


1、名称2、是否加密:3、信号强度4、是否5G信号5、代理和静态ip设置6、密码类型和密码7、连接状态ScanResult 包含:名称SSID , 信号强度 level 需要转换成 0-5, 是否5G信号 frequency 范围是否在 4900-5900 , 加密类型 capabilities 需要转换。WifiConfiguration 包含:wifi名称,wifi加密类型,wifi密码 ,是否代理和静态ip ,不包含信号强度和是否5G信号信息连接状态需要用 WifiManager 进行判断,判断是连接状态,还是断开状态!WifiInfo 判断当前连接的wifi 信息。

需要注意的是,wifi信号强度和是否5G都是通过一定的转换才能得到结果。
网上找一大堆例子,其实都是根据源码修改过来的,但是就是源码api就是没暴露!
还有就是,WifiConfiguration 不包含信号强度和是否5G信号信息,这个也让很多人懵逼,所以要自己再遍历判断一次。
WifiConfiguration 里面有 preSharedKey 对象,但是你获取保存的wifi列表信息中打印这个数据,会发现为空。
所以wifi 密码并未对外暴露。真要获取,可以通过一个配置文件获取到密码,需要系统权限。

Android 11及更新版本 wifi信息保存的位置(热点信息也在同级目录下):

date/misc/apexdata/com.android.wifi/WifiConfigStore.xml

Androi 10或旧版本自己去百度一下哈,也可以看看我之前从源码分析wifi、热点信息保存文件位置的思路:
https://blog.csdn.net/wenzhi20102321/article/details/128593458

下面是本文的主要内容,wifi 密码类型的判断,在源码中多个地方是可以找到的,但是就是没用暴露!!!

并且网上针对这个东西的分析比较少!

二、wifi密码加密类型判断

先看看系统源码时如何判断的.

1、ScanResult 中的判断和暴露的方法

/*** Describes the authentication, key management, and encryption schemes//上面的翻译:描述身份验证、密钥管理和加密方案* supported by the access point.*/public String capabilities;//目前最常用类型:wpa/wpa2public static boolean isScanResultForPskNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("PSK");}public static boolean isScanResultForWapiPskNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("WAPI-PSK");}public static boolean isScanResultForWapiCertNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("WAPI-CERT");}//企业级加密:EAP,有叫802.1 EAP,选项比较多,可能要证书public static boolean isScanResultForEapNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("EAP");}public static boolean isScanResultForEapSuiteBNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("SUITE-B-192");}//旧类型:weppublic static boolean isScanResultForWepNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("WEP");}public static boolean isScanResultForOweNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("OWE");}public static boolean isScanResultForOweTransitionNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("OWE_TRANSITION");}//比较新的加密类型:wpa3public static boolean isScanResultForSaeNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("SAE");}//既包含WPA2,也包含WPA3的情况public static boolean isScanResultForPskSaeTransitionNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("PSK") && scanResult.capabilities.contains("SAE");}

所以 加密类型还得看 ScanResult.capabilities字符包含哪些协议的字段。

这里可以看到 ScanResult 是包含了一下判断wifi 加密类型的静态方法。

其实常用的加密类型就上面有说明的几种,wpa/wap2/wap3,EAP,WEP(基本废弃),不然就是无密码NONE
虽然没有直接getType的接口,但是根据上面暴露的方法也能得到加密类型。

简单写法:

    public static String getSecurityType(ScanResult scanResult) {if (ScanResult.isScanResultForSaeNetwork(scanResult)) {return "WPA3"} else if (ScanResult.isScanResultForPskNetwork(scanResult)) {return "WPA/WPA2"} else if (ScanResult.isScanResultForWepNetwork(scanResult)) {return "WEP"} else if (ScanResult.isScanResultForEapNetwork(scanResult)) {return "802.1 EAP"} else { //最稳妥的还是,把ScanResult提到的所有类型都判断一次,最后再判断为NONEreturn "NONE"}}

上面这个封装方法只能做参考,毕竟没有判断全部类型,但是对应目前Android应用上常用判断显示是没啥问题的。

看一段获取到的 ScanResult.capabilities 打印,输出了SSID 和 capabilities 的信息:


03-29 09:38:02.479 30989 30989 I getSecurity  - noval 6 , capabilities = [WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS] // 普通手机的热点wifi,wpa2
03-29 09:38:02.479 30989 30989 I getSecurity  - KTC-SYRJB , capabilities = [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP][ESS] //路由器wifi,wap2
03-29 09:38:02.479 30989 30989 I getSecurity  - VPN , capabilities = [WPA-PSK-CCMP][WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS] //路由器wifi,wap2
03-29 09:38:02.480 30989 30989 I getSecurity  - lwz , capabilities = [ESS] //路由器无密码的wifi,NONE
03-29 09:38:02.480 30989 30989 I getSecurity  - VPN_5G , capabilities = [WPA-PSK-CCMP][WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS]
03-29 09:38:02.481 30989 30989 I getSecurity  - tts , capabilities = [WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][RSN-PSK-TKIP+CCMP][ESS][WPS]
03-29 09:38:02.484 30989 30989 I getSecurity  - Horion_fz , capabilities = [ESS]
03-29 09:38:02.484 30989 30989 I getSecurity  - KTC-SYRJB5 , capabilities = [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP][ESS]
03-29 09:38:02.485 30989 30989 I getSecurity  - 爱连不连 , capabilities = [WPA2-PSK-CCMP][RSN-PSK-CCMP][ESS]

这里可以看到加密类型是有多个协议的,所以判断wifi加密类型判断协议里面包含的字段就可以。
可以看到这里的wifi基本都是支持WPA2 的,如果没有就看是否支持WPA,再没有就看是否支持 WEP 。。。最后就是NONE。
一般是先判断高级的,再网低级的判断,WPA3(SAE) 》WPA2 》WPA,显示高级的即可。具体的判断顺序可以参考 WifiConfiguration 对类型的判断。

最后应用进行连接还有设置wifi类型,这是Int类型的type,需要查看 WifiConfiguration 中的定义了!

2、WifiConfiguration 中的判断

WifiConfiguration.java 搜索加密类型关键字:“Security type”

//下面8个加密类型就是Android中支持的加密类型,也是wifi连接需要配置的类型值/** Security type for an open network. */public static final int SECURITY_TYPE_OPEN = 0;/** Security type for a WEP network. */public static final int SECURITY_TYPE_WEP = 1;/** Security type for a PSK network. */public static final int SECURITY_TYPE_PSK = 2;/** Security type for an EAP network. */public static final int SECURITY_TYPE_EAP = 3;/** Security type for an SAE network. */public static final int SECURITY_TYPE_SAE = 4;/** Security type for an EAP Suite B network. */public static final int SECURITY_TYPE_EAP_SUITE_B = 5;/** Security type for an OWE network. */public static final int SECURITY_TYPE_OWE = 6;/** Security type for a WAPI PSK network. */public static final int SECURITY_TYPE_WAPI_PSK = 7;/** Security type for a WAPI Certificate network. */public static final int SECURITY_TYPE_WAPI_CERT = 8;//这里可以看到一共有9大类的加密类型!//WifiConfiguration 对应类型数据的设置,//系统应用中也有对 allowedKeyManagement 属性进行配置的, //其实就是和使用 setSecurityParams 方法进行配置一样,并且 setSecurityParams 更简单。public void setSecurityParams(@SecurityType int securityType) {// Clear all the bitsets.allowedKeyManagement.clear();allowedProtocols.clear();allowedAuthAlgorithms.clear();allowedPairwiseCiphers.clear();allowedGroupCiphers.clear();allowedGroupManagementCiphers.clear();allowedSuiteBCiphers.clear();switch (securityType) {case SECURITY_TYPE_OPEN:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);break;case SECURITY_TYPE_WEP:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);break;case SECURITY_TYPE_PSK:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);break;case SECURITY_TYPE_EAP:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);break;case SECURITY_TYPE_SAE:allowedProtocols.set(WifiConfiguration.Protocol.RSN);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);requirePmf = true;break;case SECURITY_TYPE_EAP_SUITE_B:allowedProtocols.set(WifiConfiguration.Protocol.RSN);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);// Note: allowedSuiteBCiphers bitset will be set by the service once the// certificates are attached to this profilerequirePmf = true;break;case SECURITY_TYPE_OWE:allowedProtocols.set(WifiConfiguration.Protocol.RSN);allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);requirePmf = true;break;case SECURITY_TYPE_WAPI_PSK:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK);allowedProtocols.set(WifiConfiguration.Protocol.WAPI);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);break;case SECURITY_TYPE_WAPI_CERT:allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT);allowedProtocols.set(WifiConfiguration.Protocol.WAPI);allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4);allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4);break;default:throw new IllegalArgumentException("unknown security type " + securityType);}}// 通过 WifiConfiguration 对象获取加密类型 Type 的int值,//值得注意的是,这个方法是私有的哦,可以自己写一个工具类,把它复制进去使用就可以/*** Fetch network type from network configuration.*/private static @WifiConfiguration.SecurityType int getNetworkType(WifiConfiguration config) {if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_SAE;} else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_PSK;} else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;} else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;} else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_EAP;} else if (WifiConfigurationUtil.isConfigForEapSuiteBNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;} else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WEP;} else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_OWE;} else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_OPEN;}throw new IllegalArgumentException("Invalid WifiConfiguration: " + config);}// 通过 ScanResult 对象获取加密类型 Type 的int值,//值得注意的是,这个方法是私有的哦,可以自己写一个工具类,把它复制进去使用就可以/*** Fetch network type from scan result.*/private static @WifiConfiguration.SecurityType int getNetworkType(ScanResult scanResult) {if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_SAE;} else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;} else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;} else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_PSK;} else if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;} else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_EAP;} else if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_WEP;} else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_OWE;} else if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) {return WifiConfiguration.SECURITY_TYPE_OPEN;} else {throw new IllegalArgumentException("Invalid ScanResult: " + scanResult);}}//还有个 getSsidAndSecurityTypeString 方法,但是是hide的,同样在应用中无法使用!// allowedKeyManagement 属性是public 的,所以也是可以参考该方法对wifi类型加密显示的String/** @hide*  return the SSID + security type in String format.*/public String getSsidAndSecurityTypeString() {String key;if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];} else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)|| allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];} else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length&& wepKeys[wepTxKeyIndex] != null) {key = SSID + "WEP";} else if (allowedKeyManagement.get(KeyMgmt.OWE)) {key = SSID + KeyMgmt.strings[KeyMgmt.OWE];} else if (allowedKeyManagement.get(KeyMgmt.SAE)) {key = SSID + KeyMgmt.strings[KeyMgmt.SAE];} else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];} else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_PSK];} else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_CERT];} else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {key = SSID + KeyMgmt.strings[KeyMgmt.OSEN];} else {key = SSID + KeyMgmt.strings[KeyMgmt.NONE];}return key;}//这个方法是暴露的,可以访问,基本是返回key的值,比如wpa2的wifi名称:WiFiName,返回的字符串是(注意是有引号的): "WifiName"WPA_PSKpublic String getKey() {// Passpoint ephemeral networks have their unique identifier set. Return it as is to be// able to match internally.if (mPasspointUniqueId != null) {return mPasspointUniqueId;}String key = getSsidAndSecurityTypeString();if (!shared) {key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();}return key;}public BitSet allowedProtocols;//为啥上面的 allowedKeyManagement 对象是会有数据,//其实就是 WifiConfiguration 创建的是会调用了 setSecurityParams方法!

其实 WifiConfiguration 里面定义了内部类 KeyMgmt 里面细分了wifi加密类型的字符串和类型值。实际用处不大。

通过上面的代码可以看到,即使是已保存的wifi列表,并没有直接暴露的加密类型Type的接口,

不过看了源码后,封装一个getType和getTypeString 还是很简单的,下面是一个示例:

//获取Type 的int值,直接拿源码部分过来就可以public static int getNetworkType(WifiConfiguration config) {if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_SAE;} else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_PSK;} else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;} else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;} else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_EAP;} else if (WifiConfigurationUtil.isConfigForEapSuiteBNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;} else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_WEP;} else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_OWE;} else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {return WifiConfiguration.SECURITY_TYPE_OPEN;}throw new IllegalArgumentException("Invalid WifiConfiguration: " + config);}//获取Type 的String 值,从源码 getSsidAndSecurityTypeString 方法去除SSID 即可。public String getSecurityTypeString(WifiConfiguration config)) {String key;allowedKeyManagement = config.allowedKeyManagement;if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {key = KeyMgmt.strings[KeyMgmt.WPA_PSK];} else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)|| allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {key = KeyMgmt.strings[KeyMgmt.WPA_EAP];} else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length&& wepKeys[wepTxKeyIndex] != null) {key = "WEP";} else if (allowedKeyManagement.get(KeyMgmt.OWE)) {key = KeyMgmt.strings[KeyMgmt.OWE];} else if (allowedKeyManagement.get(KeyMgmt.SAE)) {key = KeyMgmt.strings[KeyMgmt.SAE];} else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {key = KeyMgmt.strings[KeyMgmt.SUITE_B_192];} else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {key = KeyMgmt.strings[KeyMgmt.WAPI_PSK];} else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {key = KeyMgmt.strings[KeyMgmt.WAPI_CERT];} else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {key = KeyMgmt.strings[KeyMgmt.OSEN];} else {key = KeyMgmt.strings[KeyMgmt.NONE];}return key;}

上面没有做Type int <–> String 直接的转换,如果要可以自己做一个!

3、SettingLib 中 AccessionPoint 中的判断

看过原生Settings Wifi连接部分的代理就会值得,里面的Wifi条目用的是 AccessionPoint 对象进行数据判断。

AccessionPoint 对象是 WifiConfiguration 对象的进一步封装而成。

自己写的应用的封装其实可以参考 AccessionPoint ,更加实用简单。

//这里可以看到只定义了7大类的加密类型,其他的加密类型在实际应用中基本用不到!public static final int SECURITY_NONE = 0;public static final int SECURITY_WEP = 1;public static final int SECURITY_PSK = 2;public static final int SECURITY_EAP = 3;public static final int SECURITY_OWE = 4; //值得注意的是,4和5没和 WifiConfiguration的加密类型值对应上,不要用错了!public static final int SECURITY_SAE = 5;public static final int SECURITY_EAP_SUITE_B = 6;public static final int SECURITY_MAX_VAL = 7; // Has to be the lastprivate String ssid; //wifi名称private int security; //加密类型int值//这里可以看到 AccessionPoint 内部是包含 WifiConfiguration 对象的!public WifiConfiguration getConfig() {return mConfig;}public String getSsidStr() {return this.ssid;}//获取加密类型值public int getSecurity() {return this.security;}//获取wifi 加密类型,参数:是否是简写名称,一般用true即可public String getSecurityString(boolean var1) {Context var2 = this.mContext;if (!this.isPasspoint() && !this.isPasspointConfig()) {if (this.mIsPskSaeTransitionMode) {return var1 ? var2.getString(string.wifi_security_short_psk_sae) : var2.getString(string.wifi_security_psk_sae);} else if (this.mIsOweTransitionMode) {return var1 ? var2.getString(string.wifi_security_short_none_owe) : var2.getString(string.wifi_security_none_owe);} else {switch(this.security) { //判断七大类case 0:default:return var1 ? "" : var2.getString(string.wifi_security_none);case 1:return var1 ? var2.getString(string.wifi_security_short_wep) : var2.getString(string.wifi_security_wep);case 2:switch(this.pskType) {case 0:default:return var1 ? var2.getString(string.wifi_security_short_psk_generic) : var2.getString(string.wifi_security_psk_generic);case 1:return var1 ? var2.getString(string.wifi_security_short_wpa) : var2.getString(string.wifi_security_wpa);case 2:return var1 ? var2.getString(string.wifi_security_short_wpa2) : var2.getString(string.wifi_security_wpa2);case 3:return var1 ? var2.getString(string.wifi_security_short_wpa_wpa2) : var2.getString(string.wifi_security_wpa_wpa2);}case 3:switch(this.mEapType) {case 0:default:return var1 ? var2.getString(string.wifi_security_short_eap) : var2.getString(string.wifi_security_eap);case 1:return var1 ? var2.getString(string.wifi_security_short_eap_wpa) : var2.getString(string.wifi_security_eap_wpa);case 2:return var1 ? var2.getString(string.wifi_security_short_eap_wpa2_wpa3) : var2.getString(string.wifi_security_eap_wpa2_wpa3);}case 4:return var1 ? var2.getString(string.wifi_security_short_owe) : var2.getString(string.wifi_security_owe);case 5:return var1 ? var2.getString(string.wifi_security_short_sae) : var2.getString(string.wifi_security_sae); //wpa3case 6:return var1 ? var2.getString(string.wifi_security_short_eap_suiteb) : var2.getString(string.wifi_security_eap_suiteb);}}} else {return var1 ? var2.getString(string.wifi_security_short_eap) : var2.getString(string.wifi_security_eap);}}// 重点还是对security 类型的判断!下面进行分析://扫描的wifi列表private final ArraySet<ScanResult> mScanResults = new ArraySet();// AccessPoint 的构造方法,设置对象参数AccessPoint(Context context, Collection<ScanResult> results) {mContext = context;setScanResults(results);updateKey();}void setScanResults(Collection<ScanResult> var1) {。。。synchronized(this.mLock) {this.mScanResults.clear();this.mScanResults.addAll(var1);}}private void updateBestRssiInfo() {//遍历获取到对应的ScanResult ,进行数据设置等操作this.security = getSecurity(this.mContext, var1);}//根据 ScanResult.capabilities 判断加密类型private static int getSecurity(Context var0, ScanResult var1) {boolean var2 = var1.capabilities.contains("WEP");boolean var3 = var1.capabilities.contains("SAE");boolean var4 = var1.capabilities.contains("PSK");boolean var5 = var1.capabilities.contains("EAP_SUITE_B_192");boolean var6 = var1.capabilities.contains("EAP");boolean var7 = var1.capabilities.contains("OWE");boolean var8 = var1.capabilities.contains("OWE_TRANSITION");WifiManager var9;if (var3 && var4) {var9 = (WifiManager)var0.getSystemService("wifi");return var9.isWpa3SaeSupported() ? 5 : 2;} else if (var8) {var9 = (WifiManager)var0.getSystemService("wifi");return var9.isEnhancedOpenSupported() ? 4 : 0;} else if (var2) {return 1;} else if (var3) {return 5;} else if (var4) {return 2;} else if (var5) {return 6;} else if (var6) {return 3;} else {return var7 ? 4 : 0;}}//信号强度获取,注意这里返回的值是0-4,是不需要转换的!//这里可以看到是通过WifiManager 的接口转换的wifi信号强度public int getLevel() {return this.getWifiManager().calculateSignalLevel(this.mRssi);}

从上面的代码看 AccessionPoint 的类型判断也是基于 ScanResult.capabilities 的字符串!

值得注意的是上面定义的类型值和 WifiConfiguration 对象的加密类型值未对应,
最终连接wifi 使用的是 WifiConfiguration 对象的配置!

4、ScanResultUtil 中的判断

ScanResultUtil.java 类是 framework 内部使用的一个工具类

frameworks\opt\net\wifi\service\java\com\android\server\wifi\util\ScanResultUtil.java

//根据 ScanResult 创建 WifiConfiguration对象public static WifiConfiguration createNetworkFromScanResult(ScanResult scanResult) {WifiConfiguration config = new WifiConfiguration();config.SSID = createQuotedSSID(scanResult.SSID);setAllowedKeyManagementFromScanResult(scanResult, config);return config;}//给wifi名称添加引号public static String createQuotedSSID(String ssid) {return "\"" + ssid + "\"";}//给 WifiConfiguration 设置加密类型参数public static void setAllowedKeyManagementFromScanResult(ScanResult scanResult,WifiConfiguration config) {if (isScanResultForSaeNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);} else if (isScanResultForWapiPskNetwork(scanResult)) {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK);} else if (isScanResultForWapiCertNetwork(scanResult)) {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT);} else if (isScanResultForPskNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);} else if (isScanResultForEapSuiteBNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);} else if (isScanResultForEapNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);} else if (isScanResultForWepNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);} else if (isScanResultForOweNetwork(scanResult)) {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);} else {config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);}}//判断加密类型。。。,ScanResult 也有一样的静态方法!public static boolean isScanResultForPskNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("PSK");}public static boolean isScanResultForWapiPskNetwork(ScanResult scanResult) {return scanResult.capabilities.contains("WAPI-PSK");}

其实后面对象 WifiConfiguration/AccessionPoint 的加密类型都是基于扫描到的 ScanResult.capabilities 进行一定的封装转换得到的。

5、总结一下 ScanResult 、 WifiConfiguration 、 AccessionPoint 这三个类对象的联系和区别

(1) 各自特点和联系


ScanResult ,扫描到的wifi列表的单个 wifi 信息对象,普通应用中使用WifiConfiguration , 已保存的单个 wifi 数据对象,提取了ScanResult 对象部分信息, 普通应用中使用AccessionPoint ,提取了ScanResult 对象部分信息,比 WifiConfiguration 做了更多的封装(加了加密类型字符串和int值,wifi信号的获取等), 
一般是系统应用使用,比如原生Settings。并且必要条件是导入SettingsLib这个系统Jar包。
Settings 应用中,扫描到的wifi 信息,已经封装到 AccessionPoint 对象。

可以看到 WifiConfiguration 和 AccessionPoint ,都是基于 ScanResult。
但是也有特殊情况,比如隐藏的wifi,是无法扫描到的,所以不经过 ScanResult。

隐藏的wifi连接,只要输入wifi名称,wifi加密类型参数 和 wifi 密码 即可。

那么问题来了,直接添加的wifi,即使连接成功也无法显示是否是 5G信号和wifi信号强度???

哈哈,如果是添加的网络,连接成功的话,是可以显示信号强度和是否5G的!通过 WifiInfo 这个对象即可获取到该信息。

WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);// 取得WifiInfo对象WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();

WifiInfo 的关键方法:

//获取WiFi名称,加了引号处理public String getSSID() {if (mWifiSsid != null) {String unicode = mWifiSsid.toString();if (!TextUtils.isEmpty(unicode)) {return "\"" + unicode + "\"";} else {String hex = mWifiSsid.getHexString();return (hex != null) ? hex : WifiManager.UNKNOWN_SSID;}}return WifiManager.UNKNOWN_SSID;}//获取wifi信号,未经过处理的值,并非0-4的值public int getRssi() {return mRssi;}/*** @hide*/public boolean is24GHz() {return ScanResult.is24GHz(mFrequency);}/*** @hide*/@UnsupportedAppUsagepublic boolean is5GHz() {return ScanResult.is5GHz(mFrequency);}//注意上面判断是否5G的方法是隐藏的,无法调用,下面的方法是暴露的!//并且 ScanResult.is5GHz方法也是隐藏的,无法调用,不过看源码就能看出他判断过程//通过获取到的 mFrequency 进行判断即可。public int getFrequency() {return mFrequency;}

好像也没有太大信息,刚好补充了 WifiConfiguration 对象未包含信号强度和是否5G信号信息的缺陷!

(2)区别

区别,无非就是哪些信息不被包含。

ScanResult 包含:名称SSID , 信号强度 level 需要转换成 0-5, 是否5G信号 frequency 范围是否在 4900-5900 , 加密类型 capabilities 需要转换。WifiConfiguration 包含:wifi名称,wifi加密类型,wifi密码(无法通过对象获取) ,是否代理和静态ip ProxyInfo ,不包含信号强度和是否5G信号信息AccessionPoint 包含:WifiConfiguration对象,wifi名称,wifi加密类型,信号强度(如果已连接) ,不包含是否5G信号信息连接状态需要用 WifiManager 进行判断Wifi状态,判断是连接状态,还是断开状态,连接中,断开中。。。!WifiInfo 判断当前连接的wifi 信息 包含:名称,信号强度,是否5G。

总的来说,ScanResult 包含的信息是最多的,但是通过该对象无法判断是当前wifi是否是连接状态。
WifiConfiguration 多加了 代理对象和静态ip设置对象
AccessionPoint 包含了WifiConfiguration,并且增加获取wifi加密类型字符串,信号强度的方法

三、自定义wifi连接网络对加密类型封装

通过上面加密类型的代码,自己写一个加密类型的工具类应该是没啥问题了。

1、思路

如果自己写一个wifi demo,如果要每个wifi 都包含上面的全部关键信息,
那么可以自己定义一个Bean,定义所有关键信息变量,
还有一个懒的方法,WifiBean 里面包含两个对象:ScanResult 和 WifiConfiguration,那么就可以判断所有属性了;
如果未连接过的wifi ,WifiConfiguration 为空,已连接过的wifi WifiConfiguration对象是有数据的。

总的来说,以 ScanResult 列表为准,并且对应判断已保存的wifi (一般比较少),判断每一个wifi 名称(SSID)和设备地址(BSSID)。

2、WifiBean

(1)WifiBean对象的定义

public class WifiBean {//包含:名称SSID , 信号强度 level 0-5, 是否5G信号 frequency 范围是否在 4900-5900 , 加密类型 capabilitiespublic ScanResult mScanResult;//包含:是否代理和静态ippublic WifiConfiguration mWifiConfiguration;//是否已连接,用于判断wifi列表顺序显示,已连接排第一(只有一个),已保存排第二(可能有多个),其他排后面public int mState = 0;
}

3、WifiUtils

//获取wifi 密码类型数值,对标WifiConfiguration  security types,需要自适配/*** Security type for an open network.*/public static final int SECURITY_TYPE_OPEN = 0;/*** Security type for a WEP network.*/public static final int SECURITY_TYPE_WEP = 1; //wep/*** Security type for a PSK network.*/public static final int SECURITY_TYPE_PSK = 2; //wpa/wpa2/*** Security type for an EAP network.*/public static final int SECURITY_TYPE_EAP = 3; //802.1x eap/*** Security type for an SAE network.*/public static final int SECURITY_TYPE_SAE = 4; //wap3/*** Security type for an EAP Suite B network.*/public static final int SECURITY_TYPE_EAP_SUITE_B = 5; //802.1x eap b/*** Security type for an OWE network.*/public static final int SECURITY_TYPE_OWE = 6; //后面的情况不判断了,这里就是other!/*** Security type for a WAPI PSK network.*/public static final int SECURITY_TYPE_WAPI_PSK = 7;/*** Security type for a WAPI Certificate network.*/public static final int SECURITY_TYPE_WAPI_CERT = 8;//这里只适配0-5,加上第六种 Others,显示为OWE/WAPI,后面三种基本用不到!//显示给用户的wifi 加密类型public static final String NONE_STRING = "NONE";public static final String WEP_STRING = "WEP";public static final String PSK_STRING = "WPA/WPA2";public static final String EAP_STRING = "802.1X/EAP";public static final String SAE_STRING = "WPA3";public static final String EAP_B_STRING = "802.1X/EAP_B";public static final String OWE_WAPI = "OWE/WAPI"; //其他类型//关键字(内部使用判断协议包含关系),可以依据ScanResult的静态判断协议方法:public static final String CAPABILITIES_WEP = "WEP";public static final String CAPABILITIES_PKS = "PSK"; //wpa/wap2public static final String CAPABILITIES_EAP = "EAP";public static final String CAPABILITIES_SAE = "SAE"; //wpa3public static final String CAPABILITIES_EAP_B = "SUITE-B";public static final String CAPABILITIES_WAPI = "WAPI";public static final String CAPABILITIES_OWE = "OWE";//获取wifi 密码类型数值,参数为:ScanResult.capabilitiespublic static int getWifiSecurityInt(String capabilities) { //扫描的ScanResult.capabilities// 参考 WifiConfiguration getSsidAndSecurityTypeString() 并不完全if (capabilities.contains(CAPABILITIES_SAE)) {return SECURITY_TYPE_SAE;} else if (capabilities.contains(CAPABILITIES_EAP_B)) {return SECURITY_TYPE_EAP_SUITE_B;} else if (capabilities.contains(CAPABILITIES_EAP)) {return SECURITY_TYPE_EAP;} else if (capabilities.contains(CAPABILITIES_PKS)) {return SECURITY_TYPE_PSK;} else if (capabilities.contains(CAPABILITIES_WEP)) {return SECURITY_TYPE_WEP;} else if (capabilities.contains(CAPABILITIES_WAPI) || capabilities.contains(CAPABILITIES_OWE)) { //其他类型判断return SECURITY_TYPE_OWE;}//最后返回无密码情况return SECURITY_TYPE_OPEN;}//获取wifi 密码类型字符,参数为:ScanResult.capabilities//判断顺序参考:ScanResultUtil.setAllowedKeyManagementFromScanResult// 先->后:WPA3->WAPI(常用的最后两种)-->PKS(WPA/WPA2)-->EAP_B-->EAP(802.1)-->WEP-->OWE(特殊的无密wifi)-->OPEN//不过可以参考AccessPoint,不判断 WAPI 和 OWE ,因为基本不用用到。public static String getWifiSecurityString(String capabilities) { //扫描的ScanResult.capabilities// 参考 WifiConfiguration getSsidAndSecurityTypeString() 并不完全if (capabilities.contains(CAPABILITIES_SAE)) {return SAE_STRING;} else if (capabilities.contains(CAPABILITIES_EAP_B)) {return EAP_B_STRING;} else if (capabilities.contains(CAPABILITIES_EAP)) {return EAP_STRING;} else if (capabilities.contains(CAPABILITIES_PKS)) {return PSK_STRING;} else if (capabilities.contains(CAPABILITIES_WEP)) {return WEP_STRING;} else if (capabilities.contains(CAPABILITIES_WAPI) || capabilities.contains(CAPABILITIES_OWE)) { //其他类型判断return SAE_STRING;}return NONE_STRING; //最后返回无密码情况}//wifi 信号数值转换 -88,-77,-66,-55 --> 0-4 ,5格信号,参数为参数为:ScanResult.rssi// frameworks\opt\net\wifi\service\java\com\android\server\wifi util\RssiUtil.java//RssiUtil.calculateSignalLevel(mContext, rssi);public static int calculateSignalLevel(int rssi) {int[] thresholds = {-88, -77, -66, -55};for (int level = 0; level < thresholds.length; level++) {if (rssi < thresholds[level]) {return level;}}return thresholds.length;}public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160;public static final int BAND_5_GHZ_END_FREQ_MHZ = 5865;//是否是5G信号,参数为 ScanResult.frequencypublic static boolean is5GHz(int freqMhz) {return freqMhz >=  ScanResult.BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= ScanResult.BAND_5_GHZ_END_FREQ_MHZ;}//根据加密类型值和密码,合成 WifiConfiguration 对象@RequiresApi(api = Build.VERSION_CODES.R)public static  WifiConfiguration geWifiConfiguration(String wifiName, int securityType, String password) {WifiConfiguration wifiConfiguration = new WifiConfiguration();//名称配置wifiConfiguration.SSID = convertToQuotedString(wifiName); //wifi 名称的必现加双引号wifiConfiguration.hiddenSSID = true; //部分隐藏的wifi,如果不加该属性会不显示//密码配置switch (securityType) { //这个判断可以按0-6 的顺序case SECURITY_TYPE_OPEN: // 0//无密码的情况,一定不能设置密码字符串,否则会连接不上wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);break;case SECURITY_TYPE_WEP: //1 wepwifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);if (password.length() != 0) {int length = password.length();// WEP-40, WEP-104, and 256-bit WEP (WEP-232?)if ((length == 10 || length == 26 || length == 58)&& password.matches("[0-9A-Fa-f]*")) {wifiConfiguration.wepKeys[0] = password;} else {wifiConfiguration.wepKeys[0] = '"' + password + '"';}}break;case SECURITY_TYPE_PSK: //2 wpa/wap2wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);if (password.length() != 0) {if (password.matches("[0-9A-Fa-f]{64}")) {wifiConfiguration.preSharedKey = password;} else {wifiConfiguration.preSharedKey = '"' + password + '"';}}break;case SECURITY_TYPE_EAP: //3 802.1 eap//802.1X EAP,该项配置较多,不在这里配置//需要具体了解可以参考代码:packages\apps\Settings\src\com\android\settings\wifi\WifiConfigController.javawifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);break;case SECURITY_TYPE_SAE: //4 wap3wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); //4if (password.length() != 0) {wifiConfiguration.preSharedKey = '"' + password + '"';}break;case SECURITY_TYPE_EAP_SUITE_B: //5 802.1 eap_b//802.1X EAP,该项配置较多,不在这里配置wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);break;case SECURITY_TYPE_OWE: //6 其他,不做判断return null;}return wifiConfiguration;}

上面只封装了几个方法:


getWifiSecurityInt 获取加密类型值
getWifiSecurityString 获取加密类型字符串
calculateSignalLevel 计算WiFi信号强度
is5GHz 判断当前wifi 是否是5G 网络
根据密码类型和具体参数封装 WifiConfiguration 对象。

这几个方法在Android 上是没有可以直接调用的api,只能自己封装。

根据实际需求,其实也还可以进行进一步封装常用方法:

比如
获取wifi 密码, 有点难,估计要系统权限,系统保存的配置文件中有密码字符串
获取wifi 代理情况,
获取wifi 静态ip 情况
判断wifi 是否保存状态 (根据wifi名称)
判断wifi 是否连接状态 (根据wifi名称)

值得注意的是上面虽然有封装了获取 WifiConfiguration 对象的静态方法,
但是配置对象有代理和静态ip 的情况,也需要把对应信息设置进去。

四、关于其他wifi加密类型相关知识

1、Android 所有加密类型详解

加密协议介绍:

SECURITY_TYPE_WEP = 1; //比较旧的加密方式,基本很少用,不太安全更多文字介绍:https://blog.csdn.net/u013403237/article/details/50663790SECURITY_TYPE_PSK = 2; //目前常用包含WPA/WPA2更多文字介绍:https://www.jianshu.com/p/9316c433ec5f/SECURITY_TYPE_EAP = 3; //非常安全EAP 的类型,是一种企业验证的安全类型,EAP 全称叫 802.1X/EAP 他常常给误解成 802.11x。EAP 的意思就是可扩展认证协议的缩写。最常部署的 EAP 验证类型包括 EAP-MD-5、EAP-TLS、EAP-LEAP、EAP-TTLS、EAP-Fast、EAP-PEAP;所以EAP网络也是连接wifi参数最多的网络,还需要添加客户端和服务器端的证书安装。更多文字介绍:https://blog.csdn.net/hl1293348082/article/details/123888636SECURITY_TYPE_SAE = 4;SAE最早是802.11s中为mesh网络提出的基于password的认证和key生成协议[1]。在WPA2-PSK中,PMK就是PSK,直接来源于密钥;而SAE则保证任何STA pair(AP-STA,nonAP-STA)在不同的session都有不同的PMK,使用SAE认证的个人无线网络通常称为WPA3-PSK/WPA3-Personal。简单的说SAE,就是WPA2的升级,简称WPA3更多文字介绍:https://blog.csdn.net/qq_23087099/article/details/113921261SECURITY_TYPE_EAP_SUITE_B = 5;EAP网络的另一种加密形式,具体介绍查不出SECURITY_TYPE_OWE = 6;未查出相关介绍,在当前类中发现,入下介绍,Opportunististic (共产主义),大概是共享网络的一种加密格式吧。/*** Opportunististic Wireless Encryption*/public static final int OWE = 9;最后两种:SECURITY_TYPE_WAPI_X WAPI(无线网络WLANAuthenticationandPrivacyInfrastructure)是我国自主研发并大力推行的无线网络WLAN安全标准,
它通过了IEEE(注意,不是Wi-Fi)认证和授权,是一种认证和私密性保护协议,其作用类似于802.11b中的WEP,但是能提供更加完善的安全保护。

想要更多协议的了解可以看:

https://blog.csdn.net/wenzhi20102321

2、如果有同名的wifi 如何处理?

如果有同名的wifi ,如果连接其中一个后,怎么判断另外一个是否已连接?

其实每个wifi ScanResult 除了有名称ssid 外,还有 bssid ,这个是wifi 的一个固定地址,可以使用这个进行区分。

不过很多应用并没有做这个判断,如果确实遇到这样的问题,可以多判断 bssid 进行完善。

3、 wifi 的 networkId

每个连接过的wifi,都是会有一个 networkId,这个 networkId 从 0 开始递增。
这个 networkId 是保存在 WifiConfiguration 对象中的。

某个wifi 的忘记和重新连接都是可以通过这个 networkId 进行操作就可以了。

4、wifi、热点信息保存文件位置:

可以参考之前写的博客:
https://blog.csdn.net/wenzhi20102321/article/details/128593458

4、wifi 设置密码类型的不同合成 WifiConfiguration 写法

比如判断 PKS (WPA/WAP2)的WiFi 加密类型时:


//有的应用这样写:
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);//有的应用这样写:
wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);

第二种写法是Android11 之后才有的写法,其实具体实现也是往 wifiConfiguration.allowedKeyManagement 里面写入数据。

但是 有些密码类型需要写入多个数据,而第二种写法调用api就可以了,比较方便,准确。

5、wifi 已保存/已连接的情况修改数据

直接对 WifiConfiguration 对象进行修改即可,并且重新进行连接操作。

比如一般是修改代理或者静态ip 等数据,不需要修改的可以不用覆盖。

修改数据的情况,值得注意的是不要直接 new WifiConfiguration ,
而是用原来的 WifiConfiguration 再修改对应的数据可以,比如不修改密码的情况,不需要对密码参数进行设置。

6、wifi 加密类型判断错误会导致连接失败

wifi 连接类型判断错误,会导致wifi 无法连接。
但是也不是所有类型判断错误都会无法连接,
比如wpa3 类型的wifi 设置成 wpa/wpa2 ,亲测是可以正常连接的。

但是如果 wpa类型的网络,设置成 wpa3 类型,不知道能不能连接,没试!估计不能吧。
(最新的红米手机是可以发出wpa3 类型的热点的!)

还有无密码的wifi,如果设置密码字符串,也是会导致无法连接。

五、Android 加密类型使用总结

1、Android wifi 的连接都是必现要基于WifiConfiguration对象

2、wifi 扫描到的对象是 ScanResult ,已保存的wifi 对象是 WifiConfiguration

3、WiFi常用的数据基本都在 ScanResult 中,都是要经过一定的转换才能得到

4、wifi的开发要总结一个自己的封装类

5、wifi 加密类型的判断主要是针对不同类型设置不同参数合成 WifiConfiguration


http://www.ppmy.cn/news/42780.html

相关文章

MapReduce之WordCount案例实操

目录 前期准备&#xff1a; 本机测试&#xff1a; mapper阶段&#xff1a; Reduce阶段&#xff1a; Driver类&#xff1a; 集群测试&#xff1a; 前期准备&#xff1a; 因为MapReduce中案例比较多&#xff0c;所以需要单独创建一个工程 准备工作 创建工程后先改maven仓…

HarmonyOS/OpenHarmony应用开发-Stage模型ArkTS语言Ability基类

Ability模块提供对Ability生命周期、上下文环境等调用管理的能力&#xff0c;包括Ability创建、销毁、转储客户端信息等。 说明: 模块首批接口从API version 9 开始支持。模块接口仅可在Stage模型下使用。 导入模块: import Ability from ohos.app.ability.Ability; 接口说明…

数组的去重方法

1、ES6的Set方法去重 new Set是ES6新推出的一种类型。它和数组的区别在于&#xff0c;Set类型中的数据不可以有重复的值。当然&#xff0c;数组的一些方法Set也无法调用。 使用方法&#xff1a;将一个数组转化为Set数据&#xff0c;再转化回来&#xff0c;就完成了去重。 cons…

Map双列集合,Map接口常用方法,Map六大遍历,HashMap

Map接口实现类的特点 Map与Collection并列存在&#xff0c;用于保存具有映射关系的数据&#xff1a;Key-ValueMap中的key和value可以是任何引用类型的数据&#xff0c;会封装到HashMap$Node对象中。Map中的key不允许重复【把原先的value替换了】&#xff0c;原因和HashSet一样M…

SentenceTransformers介绍

SentenceTransformer使用范例 1使用SentenceTransformers获得句子向量嵌入 from sentence_transformers import SentenceTransformer#模型下载 model SentenceTransformer(paraphrase-MiniLM-L6-v2)# 编码句子 sentences [Python is an interpreted high-level general-pur…

Linux学习笔记——多线程

文章目录补充知识Linux线程概念线程的优点线程的缺点线程异常线程用途多进程的应用场景Linux进程VS线程重新理解进程进程和线程线程共享的进程资源和环境为什么线程切换的成本更低进程和线程的关系Linux线程控制POSIX线程库创建线程线程ID及进程地址空间布局线程终止线程等待线…

中国电子学会2022年06月份青少年软件编程Python等级考试试卷四级真题(含答案)

2022-06 Python四级真题 分数&#xff1a;100 题数&#xff1a;38 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1.有如下Python程序&#xff0c;包含lambda函数&#xff0c;运行该程序后&#xff0c;输出的结果是&#xff1f;&#xff08;C &#xf…

Maven项目的JDK版本不一致引发的问题

1.运行提示java: 错误: 不支持发行版本 5&#xff08;改成JDK8&#xff09; 2.运行提示java&#xff1a;-source 8 中不支持 instanceof 中的模式匹配(改成JDK17) 解决方案&#xff08;以JDK8为例&#xff09; 1.普通Maven项目 通过指定Maven插件的JDK版本解决 <build>…