Android-WiFi开发之 WifiManager

前言:

作为一名系统开发者, 对应用上 WiFi 的研发是一个 "门外汉" 的角色, 通过阅读 Android 源码, 逐渐对这一部分有了些许认识. 下方主要围绕 WifiManager 的函数系, 做了一些类似工具类的封装, 语言尽量简单, 希望对各位系统开发者能起到帮助的作用, 具体内容以 解释 + 注释 + 代码块的形式展示给大伙.

  1. 简介: WifiManager这个类, 是 Android 暴露给开发者使用的一个系统服务管理类, 其中包含对WiFi的响应的操作函数; 其隐藏掉的系统服务类为IWifiService, 为Android私有的, 其具体实现, 未暴露给用户; 只需要使用WifiManager进行函数操作完成UI, 监听对应的广播消息, 就可完成功能了. 换言之, WifiManager会调用service简介地和framework层, 驱动层进行函数调用, 然后驱动层会回调至上层, 以广播的形式实现通知; 这是目前WiFi的简单介绍;

  2. 一些简单的工具类的封装 以及 简要说明:

  • 获取 WifiManager 实例:
// 获取 WifiManager 实例. 
public static WifiManager getWifiManager(Context context) {
    return context == null ? null : (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
}

注意: 这是官方推荐的获取 WifiManager 类的方式; 其实在看源码的时候, 会有一个公共的构造函数, 但是是需要IWifiService的, 这个类是google私有的, 属于系统安全级别的API类, 所以, 调用上面的方法, 谷歌会帮你实例化IWifiService, 并且后续的连接, 忘记, 保存的真实实现都是由service来完成的;

  • 开启, 关闭 WiFi: (操作这个函数的时候, 就会触发系统回调WiFi状态发生改变的广播)
// 开启/关闭 WIFI.
public static boolean setWifiEnabled(WifiManager manager, boolean enabled) {
    return manager != null && manager.setWifiEnabled(enabled);
}
  • 获取 WiFi 硬件的状态:
// 获取 WIFI 的状态.
public static int getWifiState(WifiManager manager) {
    return manager == null ? WifiManager.WIFI_STATE_UNKNOWN : manager.getWifiState();
}

/**
 * 注意:
 * WiFi 的状态目前有五种, 分别是:
 * WifiManager.WIFI_STATE_ENABLING: WiFi正要开启的状态, 是 Enabled 和 Disabled 的临界状态;
 *  WifiManager.WIFI_STATE_ENABLED: WiFi已经完全开启的状态;
 *  WifiManager.WIFI_STATE_DISABLING: WiFi正要关闭的状态, 是 Disabled 和 Enabled 的临界状态;
 *  WifiManager.WIFI_STATE_DISABLED: WiFi已经完全关闭的状态;
 *  WifiManager.WIFI_STATE_UNKNOWN: WiFi未知的状态, WiFi开启, 关闭过程中出现异常, 或是厂家未配备WiFi外挂模块会出现的情况;
*/
  • 开始扫描 WiFi 热点, 在确认开启 WiFi 之后, 我们就可以调用 startScan() 函数开始扫描附近的热点了, 即:
// 开始扫描 WIFI. 
public static void startScanWifi(WifiManager manager) {
    if (manager != null) {
        manager.startScan();
    }
}
  • 获取扫描到的 WiFi 热点的结果:
// 获取扫描 WIFI 的热点: 
public static List<ScanResult> getScanResult(WifiManager manager) {
    return manager == null ? null : manager.getScanResult();
}
  • 获取配置好的 WiFi 信息:
// 获取已经保存过的/配置好的 WIFI 热点. 
public static List<WifiConfiguration> getConfiguredNetworks(WifiManager manager) {
    return manager == null ? null : manager.WifiConfiguration();
}

/** 
 * 注意: 
 * Android 的 WiFi 连接, 大概可以分为如下两种情况:
 * a. 无密码的, 可直接连接, 连接过程中, 此热点一直有, 不管最后是否需要其他方式进行验证操作, 但凡连接成功, 即  
 * 刻进行了对此热点的配置进行保存;
 * b. 有密码的, 暂且不论何种加密手段, 只要用户输入密码, 点击连接, 如果连接途中, 此热点一直有, 不论连接成功还
 * 是失败, 都即刻对此热点的配置进行了保存操作;  使用上述的方式获取到的WiFi的配置, 就是上面进行操作保存的WiFi配
 * 置;
 * c. 连接多个WiFi成功之后, 然后关闭WiFi, 下次开启WiFi的时候, 驱动会主动帮你连接这其中配置好的其中一个WiFi;
 * /
  • 获取对应到 ScanResult 的 WifiConfiguration, 通常, 此配置对应一个 BSSID, 可能是 null;
    List<WifiConfiguration> configs = wifiManager.getMatchingWifiConfig(scanResult);

    // 可以打印一下看具体的情况:
    if (configs == null || configs.isEmpty()) return;
    for (WifiConfiguration config : configs) {
        Log.v(TAG, "config = " + config);
    }
  • 连接WiFi: 连接 WIFI, 安卓提供了两种方式, 一种是通过配置连接, 另一种是通过 networkId 来连接, 两种方式各有使用场景, 可根据需要选择使用, 封装后的函数如下: (反射可抽取方法, 单独提炼, 此处不展示.)
// 使用 WifiConfiguration 连接. 
public static void connectByConfig(WifiManager manager, WifiConfiguration config) {
    if (manager == null) {
        return;
    }
    try {
        Method connect = manager.getClass().getDeclaredMethod("connect", WifiConfiguration.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (connect != null) {
            connect.setAccessible(true);
            connect.invoke(manager, config, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
    
// 使用 networkId 连接. 
public static void connectByNetworkId(WifiManager manager, int networkId) {
    if (manager == null) {
        return;
    }
    try {
        Method connect = manager.getClass().getDeclaredMethod("connect", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (connect != null) {
            connect.setAccessible(true);
            connect.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 保存网络:
// 保存网络. 
public static void saveNetworkByConfig(WifiManager manager, WifiConfiguration config) {
    if (manager == null) {
        return;
    }
    try {
        Method save = manager.getClass().getDeclaredMethod("save", WifiConfiguration.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (save != null) {
            save.setAccessible(true);
            save.invoke(manager, config, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 添加网络:
// 添加网络. 
public static int addNetwork(WifiManager manager, WifiConfiguration config) {
    if (manager != null) {
        manager.addNetwork(config);
    }
}
  • 忘记网络:
// 忘记网络.
public static void forgetNetwork(WifiManager manager, int networkId) {
    if (manager == null) {
        return;
    }
    try {
        Method forget = manager.getClass().getDeclaredMethod("forget", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (forget != null) {
            forget.setAccessible(true);
            forget.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 禁用网络:
// 禁用网络. 
public static void disableNetwork(WifiManager manager, int netId) {
    if (manager == null) {
        return;
    }
    try {
        Method disable = manager.getClass().getDeclaredMethod("disable", int.class, Class.forName("android.net.wifi.WifiManager$ActionListener"));
        if (disable != null) {
            disable.setAccessible(true);
            disable.invoke(manager, networkId, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 断开连接:
// 断开连接. 
public static boolean disconnectNetwork(WifiManager manager) {
    return manager != null && manager.disconnect();
}
  • 短暂禁用网络:
// 禁用短暂网络.
public static void disableEphemeralNetwork(WifiManager manager, String SSID) {
    if (manager == null || TextUtils.isEmpty(SSID)) 
        return;
        try {
        Method disableEphemeralNetwork = manager.getClass().getDeclaredMethod("disableEphemeralNetwork", String.class);
        if (disableEphemeralNetwork != null) {
            disableEphemeralNetwork.setAccessible(true);
            disableEphemeralNetwork.invoke(manager, SSID);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

小结:

  1. 如上, 针对会使用到的函数做个简单的封装, 使大家用起来更加简单明了, 希望能带给你一些方便.

  2. 如有疑问, 请简信, 或邮箱告知. 亦可下方评论区留言.

  3. qq 邮箱: 1281641968@qq.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容