Android代码连接Wifi时被系统切换到其他Wifi的问题


转载http://www.mamicode.com/info-detail-1066213.html

胖虎http://blog.csdn.net/ljphhj/article/details/48862037

Android代码连接Wifi时被系统切换到其他Wifi的问题

   
      

今天看别人写的代码时,提供了这样一个思路,所以我就记下来了。

自动重连接解决思路:

 1.遍历当前WifiConfiguration列表.

 2.找到WifiConfiguration最大priority.

 3.在创建WifiConfiguration时把priority设置为找到当前优先级最大值+1.

 4.WifiManager.updateNetwork(config);

 5.WifiManager.saveConfiguration();


转载请注明出处:

胖虎http://blog.csdn.net/ljphhj


1.首先要开启Wifi连接开关,mWifiManager.setWifiEnabled(true)


2.通过获取List<ScanResult>来获取到Wifi连接列表。(mWifiManager.getScanResults)


3.获取List<WifiConfiguration>列表。(mWifiManager.getConfiguredNetworks)


4. (1)创建配置要连接的WifiConfiguration(包括加密方式,SSID, 密码, [优先级]<-这个是这篇博文要说的重点)【如果选了这种方式,才进行第5步】  or (2)你连接第3步获取的Wifi配置列表中的一个NetworkId.(直接跳到第6步)


5.mConnectNetworkId = mWifiManager.addNetwork(WifiConfiguration),添加这个配置到Wifi Config (其实那个文件路径: /data/misc/wifi/wpa_supplicant.conf [ps: 这个文件是网上一堆"查看Wifi密码神器"的根基,包括万能Wifi钥匙噢!])


6.mWifiManager.enableNetwork(netId, true);


7.然后这边你需要等待Wifi连接上(两种方式,一种用广播,一种就是轮询咯,自己选择)


进入正题:


存在的问题(我也是请教别人得知的,有些地方可能不一定准确,如果有大神看到此博文,可以进行补充或者指正,谢谢):


Android 4.0之后加入了Roaming的机制,Android 5.0后又加入了另一个机制:auto join的机制, 两个机制大致差不多,就是当有一个SSID的信号强度,加密方式,或者其他因素计算出来的一个值(就是配置文件中的优先级的概念)比你要连接的Wifi的优先级数值要高的时候,会尝试去连接优先级较高的那个Wifi。


了解了这个存在问题,看看我们现在连接一个Wifi会遇到的问题(Android Version >= 4.0)


个人比较喜欢用图来解释,写博文随便画个图,方便大家理解。

从图中,想必可以知道这个问题出现的原因其实主要是:优先级列表,这个东东在我们Wifi断开跟某个SSID连接的时候,系统读取了一个优先级连接,判断出一个要连接的SSID,而我们只想连接我们的SSID,这样此时相当于有两个线程同时在进行,一但我们的SSID先连接上,System的连接晚我们一步连接上,就会导致我们刚连接上的SSID,马上就断开了。


有网友会自作聪明将要连接的SSID 它的WifiConfiguration的优先级配置很高(最高:100000),保证让它成为配置文件优先级最高的一个。认为这样的话,该SSID就会被系统认可,连接上我们先连接的SSID,但其实这个地方,你不能保证你写入优先级的时候在系统把配置文件中的优先级列表取出来之前。)


最后我个人的解决方案是:用跟系统设置模块相同的连接wifi的方式(即调用Connect来连接Wifi, 有时间可以去看下这块的代码,WifiSettings.java中的submit方法里面是连接逻辑,connect方法也在那里,我个人觉得应该是个队列类似的,这样的话你连接的操作和系统连接的操作应该是有先后关系的,而且Connect方法会更新一下优先级【最后连接上的Wifi优先级比较高】,所以我们要连接的SSID便获取到了最高的优先级)


解决方案:反射出系统设置连接的API(@hide)

/**
     * 通过反射出不同版本的connect方法来连接Wifi
     * 
     * @author jiangping.li
     * @param netId
     * @return
     * @since MT 1.0
     *
     */
    private Method connectWifiByReflectMethod(int netId) {
        Method connectMethod = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Logger.i(TAG, "connectWifiByReflectMethod road 1");
            // 反射方法: connect(int, listener) , 4.2 <= phone‘s android version
            for (Method methodSub : mWifiManager.getClass()
                    .getDeclaredMethods()) {
                if ("connect".equalsIgnoreCase(methodSub.getName())) {
                    Class<?>[] types = methodSub.getParameterTypes();
                    if (types != null && types.length > 0) {
                        if ("int".equalsIgnoreCase(types[0].getName())) {
                            connectMethod = methodSub;
                        }
                    }
                }
            }
            if (connectMethod != null) {
                try {
                    connectMethod.invoke(mWifiManager, netId, null);
                } catch (Exception e) {
                    e.printStackTrace();
                    Logger.i(TAG, "connectWifiByReflectMethod Android "
                            + Build.VERSION.SDK_INT + " error!");
                    return null;
                }
            }
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
            // 反射方法: connect(Channel c, int networkId, ActionListener listener)
            // 暂时不处理4.1的情况 , 4.1 == phone‘s android version
            Logger.i(TAG, "connectWifiByReflectMethod road 2");
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
                && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            Logger.i(TAG, "connectWifiByReflectMethod road 3");
            // 反射方法:connectNetwork(int networkId) ,
            // 4.0 <= phone‘s android version < 4.1
            for (Method methodSub : mWifiManager.getClass()
                    .getDeclaredMethods()) {
                if ("connectNetwork".equalsIgnoreCase(methodSub.getName())) {
                    Class<?>[] types = methodSub.getParameterTypes();
                    if (types != null && types.length > 0) {
                        if ("int".equalsIgnoreCase(types[0].getName())) {
                            connectMethod = methodSub;
                        }
                    }
                }
            }
            if (connectMethod != null) {
                try {
                    connectMethod.invoke(mWifiManager, netId);
                } catch (Exception e) {
                    e.printStackTrace();
                    Logger.i(TAG, "connectWifiByReflectMethod Android "
                            + Build.VERSION.SDK_INT + " error!");
                    return null;
                }
            }
        } else {
            // < android 4.0
            return null;
        }
        return connectMethod;
    }

Method connectMethod = connectWifiByReflectMethod(netId);
        if (connectMethod == null) {
            Logger.i(TAG,
                    "connect wifi by enableNetwork method, Add by jiangping.li");
            // 通用API
            mWifiManager.enableNetwork(netId, true);
        }






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随与博主沟通,第一间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值