Wifi连接热点

Wifi连接热点基本步骤:

WifiManager wifiManager=(WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiConfiguration config = new WifiConfiguration();
config.SSID = convertToQuotedString(scanResult.SSID);
config.BSSID = scanResult.BSSID;
.....
wifiManager.addNetwork(config);
wifiManager.saveConfiguration();
config.priority = 100; //需要设置成所有配置中的最高优先级
wifiManager.enableNetwork(networkId, false);
wifiManager.reassociate();

基本步骤都是新建或查找配置-》修改配置优化级-》使能网络ID-》连接
最后一步连接网上的资料通常是讲调用WifiManager的两个公开函数:

/**
 * Reconnect to the currently active access point, if we are currently
 * disconnected. This may result in the asynchronous delivery of state
 * change events.
 * @return {@code true} if the operation succeeded
 */
public boolean reconnect();

/**
 * Reconnect to the currently active access point, even if we are already
 * connected. This may result in the asynchronous delivery of state
 * change events.
 * @return {@code true} if the operation succeeded
 */
public boolean reassociate();

上面已经讲得很清楚了,reconnect只有当wifi是disconnect的时候才会生效,而reassociate无论当前是什么状态都会重连一次。

实测发现,reconnect在断开连接后调用,会经常连接到上次连接过的热点,而不会连接到新的热点。reassociate每次都会正确连接到新的热点,但是在部分手机上会经常出现连接成功-》断开-》连接的状态,初步分析是因为部分手机在发现断开连接后,会自动扫描并连接热点,目前已在小米,魅族的手机上发现。

调用这两个函数之前,需要设置好目标热点config的优先级,不然断开后会自动连接到优先级高的热点。

因为发现以上两个连接函数都有无法解决的问题,所以去看了一个系统自带的wifi管理器WifiSettings的源码,发现WifiSetting在连接的时候,并没有调用这两个函数,而是调用了WifiManager的一个隐藏函数connect(2.3版本及以下是调用reconnect)。通过反射可以调用这个函数,并且解决了以上的问题。这个隐藏函数在不同的系统版本上是不一样的,以下是部分定义:

 * 4.2~
 * public void connect(WifiConfiguration config, ActionListener listener)
 * 
 * 4.1.1 ~ 4.1.2
 * public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener)
 * public void connect(Channel c, WifiConfiguration config, ActionListener listener)
 * 
 * 4.0.3 ~ 4.0.4
 * public void connectNetwork(WifiConfiguration config)
 * 
 * 2.2.3 ~ 2.3.6
 * public boolean reconnect()

调用这个函数后,发现切换wifi基本上没有问题了,但是引入了其他的问题: 当wifi刚刚打开(enable)时,调用connect有很大概率让wifiManager的状态变坏,从而无法连接到热点。分析认为,当wifi刚刚打开的时候,系统会自动去连接wifi,这个时候可能状态不稳定,所以插入等待时间直到系统自动连接成功,这时再去连接其他wifi,测试后工作正常,这只是一个临时解决办法,更好的解决办法还需要深入了解wifi的运行机制。


发现仍然可能会出现问题,继续看wifisettings的源码,发现优先调用的是另一个connect 网络ID的函数,而不是connect配置函数,部分源码如下:

case MENU_ID_CONNECT: {
            if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
               connect(mSelectedAccessPoint.networkId);
            } else if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE) {
               /** Bypass dialog for unsecured networks */
                   mSelectedAccessPoint.generateOpenNetworkConfig();
                   connect(mSelectedAccessPoint.getConfig());
           } else {
                showDialog(mSelectedAccessPoint, true);
            }
            return true;
        }

然后实际测试发现没有问题了 :)

虽然问题解决了,但是为什么connect配置的函数不行呢,感觉这里面的原因是复杂的,或许保存配置用的是wifiservice,而连接使用的AsyncChannel? 这是一个值得挖掘的问题,等以后深入学习的时候再看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值