[Android WIFI开发]

前言

在Android应用层的开发中,使用到wifi相关知识点的地方并不多,所以之前对wifi开发并不熟悉,最近接到的两个硬件项目都有用到wifi并且知识点越来越深入,所以有必要记一下笔记,做一些注释。

基本使用

1.权限

Android中要使用系统功能一般都要申请权限,在6.0上可能还要手动申请权限,这里wifi需要的权限有

    
    
    
    
     // 需要系统权限 [定位权限]

其中在6.0以上设备,定位权限需要主动申请,并且如果要获取扫描wifi列表需要打开系统的定位开关。

2. WiFi相关API

[Android WIFI开发]_第1张图片
WIFI相关API

ScanResult类用于存放wifi扫描结果信息,包含ssid(wifi名称), bssid(网络接入点地址),capabilities(加密类型),frequency(传输频率),level(信号强度)等。这里的解释并不太标准,但是对应功能很形象,如果你要了解更多,可以去具体的查阅资料。

WifiConfiguration类用于存放wifi的配置信息。包括wifi的密码,加密类型,网络id(用于连接wifi)等。他的几个子类分别对应秘钥加密方式,安全协议等,这些在设置wifi配置的时候会被用到

wifiinfo类用来描述wifi属性和连接状态。暴露了一些方法给开发者调用。getBSSID(), getMacAddress(), getIpAddress(),getSSID()等

WifiManager类是framework层暴露的api,用来管理wifi。通过调用 Context.getSystemService(Context.WIFI_SERVICE)可以得到类的实例。通过他可以得到:1.已经配置的网络列表。2.当前连接的wifi。3.扫描到的wifi。4.以及一些常量表示广播的意图等

3. wifi状态及开关

/**
 * 判断wifi是否打开
 * 

需添加权限 {@code }

* * @return {@code true}: 是
{@code false}: 否 */ public static boolean getWifiEnabled() { @SuppressLint("WifiManagerLeak") WifiManager wifiManager = (WifiManager) Utils.getApp().getSystemService(Context.WIFI_SERVICE); return wifiManager.isWifiEnabled(); } /** * 打开或关闭wifi *

需添加权限 {@code }

* * @param enabled {@code true}: 打开
{@code false}: 关闭 */ public static void setWifiEnabled(final boolean enabled) { @SuppressLint("WifiManagerLeak") WifiManager wifiManager = (WifiManager) Utils.getApp().getSystemService(Context.WIFI_SERVICE); if (enabled) { if (!wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(true); } } else { if (wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(false); } } }

4. 扫描wifi

 /**
 *
 * 获取WIFI列表
 * 

需要权限{@code }

*

注意Android6.0上需要主动申请定位权限,并且打开定位开关

* * @param context 上下文 * @return wifi列表 */ public static List getWifiList(Context context) { WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); List scanResults = wm.getScanResults(); Collections.sort(scanResults, new Comparator() { @Override public int compare(ScanResult scanResult1, ScanResult scanResult2) { return scanResult2.level - scanResult1.level; } }); return scanResultsCopy; } /** * 获取当前链接的WiFi信息 * * @param context 上下文 * @return 当前wifi数据 */ public static WifiInfo getCurrentWifi (Context context) { WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); return wm.getConnectionInfo(); } public static String getWifiEncryptTypeStr (String capabilitie) { if (TextUtils.isEmpty(capabilitie)) return null; String encryptType; if (capabilitie.contains("WPA") && capabilitie.contains("WPA2")) { encryptType = "WPA/WPA2 PSK"; } else if (capabilitie.contains("WPA2")) { encryptType = "WPA2 PSK"; } else if (capabilitie.contains("WPA")) { encryptType = "WPA PSK"; } else if (capabilitie.contains("WEP")) { encryptType = "WEP"; } else { encryptType = "NONE"; } return encryptType; } /** * wifi加密方式有5种 * 0 - WPA/WPA2 PSK * 1 - WPA2 PSK * 2 - WPA PSK * 3 - WEP * 4 - NONE * @param capabilitie * @return */ public static int getWifiEncryptType (String capabilitie) { if (TextUtils.isEmpty(capabilitie)) return -1; int encryptType; if (capabilitie.contains("WPA") && capabilitie.contains("WPA2")) { encryptType = 0; } else if (capabilitie.contains("WPA2")) { encryptType = 1; } else if (capabilitie.contains("WPA")) { encryptType = 2; } else if (capabilitie.contains("WEP")) { encryptType = 3; } else { encryptType = 4; } return encryptType; }

5. 连接wifi

 /**
 * @des 连接已经保存过配置的wifi
 * @param context
 * @param ssid
 */
public static void connectWifi (Context context, String ssid) {

    Log.d(TAG, "connectWifi: 去连接wifi: " + ssid);

    if (!getWifiEnabled()) return;

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration wc = new WifiConfiguration();

    wc.SSID = "\"" + ssid + "\"";

    WifiConfiguration configuration = getWifiConfig(context, ssid);
    if (configuration != null) {
        wm.enableNetwork(configuration.networkId, true);
    }

}

/**
 * @des 连接没有配置过的wifi
 * @param context
 * @param ssid
 * @param password
 * @param encryptType
 */
public static void connectWifi (Context context, String ssid, String password, int encryptType) {

    Log.d(TAG, "connectWifi: 去连接wifi: " + ssid);

    if (!getWifiEnabled()) return;

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    WifiConfiguration wc = new WifiConfiguration();
    wc.allowedAuthAlgorithms.clear();
    wc.allowedGroupCiphers.clear();
    wc.allowedKeyManagement.clear();
    wc.allowedPairwiseCiphers.clear();
    wc.allowedProtocols.clear();

    wc.SSID = "\"" + ssid + "\"";

    WifiConfiguration configuration = getWifiConfig(context, ssid);
    if (configuration != null) {
        wm.removeNetwork(configuration.networkId);
    }

    switch (encryptType) {
        case 4://不加密
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            break;

        case 3://wep加密
            wc.hiddenSSID = true;
            wc.wepKeys[0] = "\"" + password +"\"";
            wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

            break;
        case 0: //wpa/wap2加密
        case 1: //wpa2加密
        case 2: //wpa加密

            wc.preSharedKey = "\"" + password + "\"";
            wc.hiddenSSID = true;
            wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            wc.status = WifiConfiguration.Status.ENABLED;
            break;
    }

    int network = wm.addNetwork(wc);
    wm.enableNetwork(network, true);
}

public static void disConnectWifi (Context context, int networkId) {
    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    wm.disableNetwork(networkId);
    wm.disconnect();
}

6. 获取和清除WIFI配置

/**
 * @des 清除wifi配置信息
 * @param context
 * @param ssid
 */
public static void clearWifiInfo(Context context, String ssid) {

    Log.d(TAG, "clearWifiInfo: 清除WIFI配置信息: " + ssid);

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

    String newSSID = "\"" + ssid + "\"";

    if (!(ssid.startsWith("\"") && ssid.endsWith("\""))) {
        newSSID = "\"" + ssid + "\"";
    } else {
        newSSID = ssid;
    }

    WifiConfiguration configuration = getWifiConfig(context, newSSID);
    configuration.allowedAuthAlgorithms.clear();
    configuration.allowedGroupCiphers.clear();
    configuration.allowedKeyManagement.clear();
    configuration.allowedPairwiseCiphers.clear();
    configuration.allowedProtocols.clear();

    if (configuration != null) {

        wm.removeNetwork(configuration.networkId);
        wm.saveConfiguration();
    }
}

public static WifiConfiguration getWifiConfig (Context context, String ssid) {

    Log.d(TAG, "getWifiConfig: 获取wifi配置信息: " + ssid);

    if (TextUtils.isEmpty(ssid)) return null;

    String newSSID;

    if (!(ssid.startsWith("\"") && ssid.endsWith("\""))) {
        newSSID = "\"" + ssid + "\"";
    } else {
        newSSID = ssid;
    }

    WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    List configuredNetworks = wm.getConfiguredNetworks();

    for (WifiConfiguration configuration : configuredNetworks) {
        if (newSSID.equalsIgnoreCase(configuration.SSID)) {
            return configuration;
        }
    }

    return null;
}

高级用法

1. 监听wifi状态的变化并刷新wifi列表和连接状态

2. 5Gwfif和2.4Gwifi

踩坑记录

1. wifi的ssid是带有"",所以你如果要判空是不行的,并且在连接wifi的时候要手动给ssid加上""。

2. 前文已经说了Android6.0以上要想扫描到wifi需要开启权限和手机的定位功能,不然得到的列表为空。

3. wifi的秘钥安全模式网上并没有人给出标准的答案,各个手机厂商的wifi系统上也都不一样,对于我们开发者而言,主要有5种方式也可以总结为3中:NONE(无密码模式), WEP(安全性较低), WAP PSK, WAP2 PSK, WPA/WPA2 PSK(这三种安全性较高)。需要注意的是通过capabilitie属性得到的字符串是类似 [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS] 这样的,因为wifi的加密方式是安全模式+密码加密类型组合的方式。你要通过string.contains()方法解析出其中的安全模式,上文的扫描wifi中有解析的代码。

4. 扫描列表中ssid可能为空或"",一般要剔除掉,而且wifi列表一般是根据信号强度排序。也有可能列表中出现同名的wifi,我之前遇到是因为现在的路由器同时支持5G wifi和2.4G wifi,两个wifi属于不同的频段。

5. wifi是可以设置为隐藏wifi的,设置为隐藏wifi后不能被扫描到,但是可以通过直接输入ssid和秘钥的方式连接上。

后记

Android 6.0 中的 Wifi 连接

WiFi加密方式有哪些?

你可能感兴趣的:([Android WIFI开发])