关于WifiManager开发遇到的几个坑

需求:本人搞物联网,wifi需要上网,前提需要先让wifi模组连接上路由器,存在wifi模组配网的过程。

有两种配网模式,

  • SmartLink,一种使用UDP广播技术实现的一种快速配网的技术,改技术有一个致命的缺陷,当路由不支持UPD广播,或者被封禁的时候,改技术无法使用了。

  • SoftAP,这种比较传统的方式,先让手机与wifi模组建立的热点进行连接,将需要连接的wifi路由 ssid与password告知wifi模组后,让wifi模组去连接。兼容性很好,贵在比较复杂,操作步骤多。

对于Android系统来说,因为可以对wifi进行操作,可以做到与SmartLink一样的快捷,更多的交给后台处理完成配网;将使用到WifiManager这个系统类;

坑一:WifiManager获取时产生内存泄露

引用前辈的帖子, https://www.jianshu.com/p/5d96983fc6db

坑二:addNetwork返回-1

相信很多人在这块开发的时候都不会自己一个一个字母的敲出来,网上copy一下完成了。

基本上网上的代码就这么一写,注意红框中的两个方法;

你会发现在很多请情况下addNetword都是返回-1;这将会使enableNetword 无法连接到指定的wifi中;

Google API

官方APP描述,新网络描述添加到已配置网络集。也就是说这个方法用于新的,未连接过的wifi;适当换成

//判断wifi曾经是不是连接过
 WifiConfiguration tempConfig = isExsits(ssid);
if (tempConfig != null) { 
  boolean enabled = wifiManager.enableNetwork(tempConfig.networkId, true); 
  Log.d(TAG, "enableNetwork status enable=" + enabled);
} else { 
  int netID = wifiManager.addNetwork(wifiConfig); 
  boolean enabled = wifiManager.enableNetwork(netID, true); 
  Log.d(TAG, "enableNetwork status enable=" + enabled);
}
private WifiConfiguration isExsits(String SSID) {
        if (wifiManager != null) {
            List<WifiConfiguration> existingConfigs = wifiManager
                    .getConfiguredNetworks();
            for (WifiConfiguration existingConfig : existingConfigs) {
                if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
                    return existingConfig;
                }
            }
        }
        return null;
    }

坑三:扫描获取手机附近wifi列表返回 size=0

    /**
     * 获取wifi列表
     *
     * @return
     */
    private List<ScanResult> getWifiList() {
        // 开始扫描
        wifiManager.startScan();
        // 得到扫描结果
        return wifiManager.getScanResults();
    }

坑四:连接没有密码的AP热点

把taget版本支持到28之后,发现连接AP热点怎么也连不上了,经过一段时间的测试,发现AP热点没有密码的时候, addnetword方法必然返回-1. 日了啊

搞了蛮久,WifiConfiguration的配置得增加上 “无密码” “WPA” “WEP”加密方式的配置,顺利搞定;

if (/*Open network*/) {
        // No security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.clear();
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    } else if (/*WPA*/ || /*WPA2*/) {
        //WPA/WPA2 Security
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wifiConfig.preSharedKey = "\"".concat(password).concat("\"");
    } else if (/*WEP*/) {
        // WEP Security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

        if (getHexKey(password)) wifiConfig.wepKeys[0] = password;
        else wifiConfig.wepKeys[0] = "\"".concat(password).concat("\"");
        wifiConfig.wepTxKeyIndex = 0;
    }

在Android 6.0之后,必须打开GPS才可以获取到wifi列表,想办法让客户打开GPS开关把,完美解决;

(目前miui 系统,还是无法正常连接到指定的wifi,打印log显示已经连接了,实际手机没有切换过去,不知道什么问题,有遇到这样问题的,希望可以指导下我;)引用评论3楼的方法,在连接之前先disconnect,再连接,解决;感谢!!!

2019-11-04 继续补充

坑五 关于 MIUI、华为 disconnect之后 积极连接其他wifi问题的处理

小米与华为手机断开连接后,会非常快速的连接曾经连接过的WIFI,这时 enableNetwork 方法压根抢不过系统,导致连接AP 热点失败。
引用前辈一篇文章,代码写得比较全了,里面注释也提到了这个问题 。
https://juejin.im/post/5b18c3d1f265da6e3c6b93da

说下我解决这个问题的过程,网上其实有一些极端的方法可以解决这个问题。
1、WiFiManager.disableNetwork()
使用 disableNetwork 方法,该方法是讲已经保存的wifi进行禁用,禁用之后,系统就不会自动的去连接这些连接过的WIFI,解决这个问题(华为测试过之后);
(小米去测试的时候就恶心了,MIUI系统每次操作WIFI都会提示用户,是否允许操作wifi,也就是说你保存了100个wifi的配置你得点100次允许,了勒个去!!!)
2、WifiManager.WifiLock
没法子,又得去爬谷歌的API文档了,英语不好,折磨。。。


image.png

主要使用以上三个方法,给WIFI加锁。

public class WifiLocKManager {
    // 定义WifiManager对象
    private WifiManager mWifiManager;
    // 定义一个WifiLock
    private WifiManager.WifiLock mWifiLock;

    private Context context;

    public WifiLocKManager(Context context) {
        // 取得WifiManager对象
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        //第一种方式
        creatWifiLock("WifiLocKManager");
        //第二种方式
        //解析一下三个常量
        //WIFI_MODE_SCAN_ONLY    在此Wi-Fi锁定模式下,Wi-Fi将保持活动状态,但是唯一受支持的操作是启动扫描以及随后报告扫描结果。
        // 不会尝试自动连接到记住的访问点,也不会自动执行定期扫描以查找记住的访问点。在这种模式下,应用程序必须明确请求扫描。
        //····································································
        //WIFI_MODE_FULL_LOW_LATENCY
        //在此Wi-Fi锁定模式下,Wi-Fi将优先运行以实现低延迟
        //低延迟模式进行了优化,以减少数据包延迟,因此,在进行权衡时,其他性能指标可能会受到影响
        //
        //WIFI_MODE_FULL_HIGH_PERF
        //在此Wi-Fi锁定模式下,Wi-Fi不会节电。这样可以降低数据包延迟。仅当设备连接到接入点时,锁才处于活动状态。
        //即使设备屏幕关闭或获取应用程序在后台运行,该锁定也处于活动状态。此模式将消耗更多功率,因此仅在需要此折衷时才应使用。
        //
        creatWifiLock("WifiLocKManager", WifiManager.WIFI_MODE_SCAN_ONLY);
    }

    public void creatWifiLock(String locakName, int lockType) {
        mWifiLock = mWifiManager.createWifiLock(lockType, locakName);
    }

    /**
     *  * 创建一个WifiLock
     *  *
     *  * @param locakName 名称
     *  
     */
    public void creatWifiLock(String locakName) {
        mWifiLock = mWifiManager.createWifiLock(locakName);
    }

    /**
     *  * 锁定WifiLock
     *  
     */
    public void acquireWifiLock() {
        mWifiLock.acquire();
    }

    /**
     *  * 解锁WifiLock
     *  
     */
    public void releaseWifiLock() {
// 判断时候锁定
        if (mWifiLock.isHeld()) {
            mWifiLock.release();
        }
    }
}

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

推荐阅读更多精彩内容